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 `
'