Fiberつづき〜3
23時をまわり雨が降ってきた。まだまだ蒸し暑い。
さて、Ruby1.8.xでも、Poor Man's FibersといってFiberと同様の実装を行ってるらしいので、ソースを覗いてみた。Queueを使って実装している。
Queueはスレッド間のFIFO(first in first out)の通信路です。スレッドが空のqueueを読み出そうとすると停止します。queueになんらかの情報が書き込まれると実行は再開されます。
never_block.rbをみると、例えばFiberクラスのinitializeメソッドでスレッドを生成し、空のQueueである@resumeをpopして、ブロックを実行させようとしているが、空なので停止(slepp)する。resumeメソッド(ここには引用してない)で@resumeにデータを突っ込むと、スレッドがrun状態に切り替わるといった具合。
def initialize raise ArgumentError, 'new Fiber requires a block' unless block_given? @yield = Queue.new @resume = Queue.new @thread = Thread.new{ @yield.push [ *yield(*@resume.pop) ] } @thread.abort_on_exception = true @thread[:fiber] = self end
前回、Fiberの挙動を試してみたけど、同じように動作した。
さあ、続いてはNeverBlockを体感しようと思い、諸々Gemをインストールしようと思ったが、うまくいかず、http://www.espace.com.eg/neverblock/downloadsに沿って、
If you're having troubles getting the gems then you can get their sources then build and install them locally.
Gemをビルドして、ローカルインストールした。
ここにneverblock_postgresqlアダプタのサンプルが記載されていて、でもMySQLしかPCにはいっていないので、折角MySQLにも対応してくれてるわけだし、MySQLでやってみようと思いつく。が・・・サンプルコード通りではまずいみたいなので変えてるところがある。さんぷるでは40行目がActiveRecord::DBとなってたりとか。2行目をついかしたりとか。してるが、結果うまくいってない。Ruby1.9でやってます。
1 require 'neverblock' 2 require 'eventmachine' 3 require 'activerecord' 4 5 class Event < ActiveRecord::Base 6 end 7 8 def test_msql(count) 9 t = Time.now 10 count.times do 11 db_block 12 end 13 puts "Blocking time: #{Time.now - t}" 14 end 15 16 def test_nb_msql(count) 17 i = 0 18 pool = FiberPool.new(10) 19 t = Time.now 20 count.times do 21 pool.spawn do 22 db_block 23 i += 1 24 puts "NeverBlock time: #{Time.now - t}" if i == count 25 end 26 end 27 end 28 29 def db_block 30 Event.transaction do 31 user_count = Event.count 32 user = Event.create({:name => 'xyz', :latitude => '111'}) 33 raise "user not inserted" if Event.count != user_count + 1 34 user.destroy 35 end 36 end 37 38 #EventMachine.run do 39 EM.run do 40 ActiveRecord::Base.establish_connection( 41 # ActiveRecord::Base.neverblock_mysql_connection( 42 :adapter => "neverblock_mysql", 43 :host => "localhost", 44 :database => "XXXXX_development", 45 :username => "XXXXX", 46 :connection => 8, 47 :socket => "/var/run/mysqld/mysqld.sock" 48 ) 49 count = 500 50 test_msql(count) 51 test_nb_msql(count) 52 end
FiberedMysqlConnectionクラスのインスタンス変数@ioがnil。@io = IO.new(socket)のところ?
ruby 1.9.0 (2008-08-26 revision 18849) [i686-linux]
~/ruby1904/lib/ruby/gems/1.9.0/gems/neverblock-0.1.4/lib/never_block/db/fibered_mysql_connection.rb:74: warning: instance variable @io not initialized
~/ruby1904/lib/ruby/gems/1.9.0/gems/eventmachine-0.12.2/lib/eventmachine.rb:754:in `attach': undefined method `fileno' for nil:NilClass (NoMethodError)
from ~/ruby1904/lib/ruby/gems/1.9.0/gems/neverblock-0.1.4/lib/never_block/db/fibered_mysql_connection.rb:74:in `register_with_event_loop'
from ~/ruby1904/lib/ruby/gems/1.9.0/gems/neverblock-0.1.4/lib/active_record/connection_adapters/neverblock_mysql_adapter.rb:54:in `block in connect'
from ~/ruby1904/lib/ruby/gems/1.9.0/gems/neverblock-0.1.4/lib/never_block/db/pooled_fibered_mysql_connection.rb:13:in `block in initialize'
from ~/ruby1904/lib/ruby/gems/1.9.0/gems/neverblock-0.1.4/lib/never_block/pool/fibered_connection_pool.rb:47:in `call'
from ~/ruby1904/lib/ruby/gems/1.9.0/gems/neverblock-0.1.4/lib/never_block/pool/fibered_connection_pool.rb:47:in `block in initialize'
from ~/ruby1904/lib/ruby/gems/1.9.0/gems/neverblock-0.1.4/lib/never_block/pool/fibered_connection_pool.rb:46:in `times'
from ~/ruby1904/lib/ruby/gems/1.9.0/gems/neverblock-0.1.4/lib/never_block/pool/fibered_connection_pool.rb:46:in `initialize'
from ~/ruby1904/lib/ruby/gems/1.9.0/gems/neverblock-0.1.4/lib/never_block/db/pooled_fibered_mysql_connection.rb:12:in `new'
from ~/ruby1904/lib/ruby/gems/1.9.0/gems/neverblock-0.1.4/lib/never_block/db/pooled_fibered_mysql_connection.rb:12:in `initialize'
from ~/ruby1904/lib/ruby/gems/1.9.0/gems/neverblock-0.1.4/lib/active_record/connection_adapters/neverblock_mysql_adapter.rb:40:in `new'
from ~/ruby1904/lib/ruby/gems/1.9.0/gems/neverblock-0.1.4/lib/active_record/connection_adapters/neverblock_mysql_adapter.rb:40:in `connect'
from ~/ruby1904/lib/ruby/gems/1.9.0/gems/activerecord-2.1.1/lib/active_record/connection_adapters/mysql_adapter.rb:186:in `initialize'
from ~/ruby1904/lib/ruby/gems/1.9.0/gems/neverblock-0.1.4/lib/active_record/connection_adapters/neverblock_mysql_adapter.rb:78:in `new'
from ~/ruby1904/lib/ruby/gems/1.9.0/gems/neverblock-0.1.4/lib/active_record/connection_adapters/neverblock_mysql_adapter.rb:78:in `neverblock_mysql_connection'
from ~/ruby1904/lib/ruby/gems/1.9.0/gems/activerecord-2.1.1/lib/active_record/connection_adapters/abstract/connection_specification.rb:292:in `connection='
from ~/ruby1904/lib/ruby/gems/1.9.0/gems/activerecord-2.1.1/lib/active_record/connection_adapters/abstract/connection_specification.rb:260:in `retrieve_connection'
from ~/ruby1904/lib/ruby/gems/1.9.0/gems/activerecord-2.1.1/lib/active_record/connection_adapters/abstract/connection_specification.rb:78:in `connection'
from ~/ruby1904/lib/ruby/gems/1.9.0/gems/neverblock-0.1.4/lib/never_block/frameworks/activerecord.rb:18:in `transaction'
from nb_smpl.rb:30:in `db_block'
from nb_smpl.rb:11:in `block in test_msql'
from nb_smpl.rb:10:in `times'
from nb_smpl.rb:10:in `test_msql'
from nb_smpl.rb:48:in `block in'
from ~/ruby1904/lib/ruby/gems/1.9.0/gems/eventmachine-0.12.2/lib/eventmachine.rb:224:in `call'
from ~/ruby1904/lib/ruby/gems/1.9.0/gems/eventmachine-0.12.2/lib/eventmachine.rb:224:in `run_machine'
from ~/ruby1904/lib/ruby/gems/1.9.0/gems/eventmachine-0.12.2/lib/eventmachine.rb:224:in `run'
from nb_smpl.rb:39:in `'