ruby - Understanding Celluloid Concurrency -


following celluloid codes.

  1. client1.rb 1 of 2 clients. (i named client 1)

  2. client2.rb 2nd of 2 clients. (named client 2 )

note:

the difference between above 2 clients text passed server. i.e ('client-1' , 'client-2' respectively)

on testing 2 clients (by running them side side) against following 2 servers (one @ time). found strange results.

  1. server1.rb (a basic example taken readme.md of celluloid-zmq)

    using example server 2 above clients resulted in parallel executions of tasks.

output

ruby server1.rb  received @ 04:59:39 pm , message client-1 going sleep received @ 04:59:52 pm , message client-2 

note:

the client2.rb message processed when client1.rb request on sleep.(mark of parallelism)

  1. server2.rb

    using example server 2 above clients did not resulted in parallel executions of tasks.

output

ruby server2.rb  received @ 04:55:52 pm , message client-1 going sleep received @ 04:56:52 pm , message client-2 

note:

the client-2 ask wait 60 seconds since client-1 sleeping(60 seconds sleep)

i ran above test multiple times resulted in same behaviour.

can explain me results of above tests that.

question: why celluloid made wait 60 seconds before can process other request i.e noticed in server2.rb case.?

ruby version

ruby -v

ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin13.0]

using gists, verified issue can reproduced in mri 2.2.1 jruby 1.7.21 , rubinius 2.5.8 ... difference between server1.rb , server2.rb use of displaymessage , message class method in latter.


use of sleep in displaymessage out of celluloid scope.

when sleep used in server1.rb using celluloid.sleep in actuality, when used in server2.rb using kernel.sleep ... locks mailbox server until 60 seconds have passed. prevents future method calls on actor processed until mailbox processing messages ( method calls on actor ) again.

there 3 ways resolve this:

  • use defer {} or future {} block.

  • explicitly invoke celluloid.sleep rather sleep ( if not explicitly invoked celluloid.sleep, using sleep end calling kernel.sleep since displaymessage not include celluloid server )

  • bring contents of displaymessage.message handle_message in server1.rb; or @ least server, in celluloid scope, , use correct sleep.


the defer {} approach:

def handle_message(message)   defer {     displaymessage.message(message)   } end 

the celluloid.sleep approach:

class displaymessage     def self.message(message)       #de ...       celluloid.sleep 60     end end 

not scope issue; it's asynchrony.

to reiterate, deeper issue not scope of sleep ... that's why defer , future best recommendation. post here came out in comments:

using defer or future pushes task cause actor become tied thread. if use future, can return value once task done, if use defer can fire & forget.

but better yet, create actor tasks tend tied up, , pool other actor... if defer or future don't work you.

i'd more happy answer follow-up questions brought question; have active mailing list, , irc channel. generous bounties commendable, plenty of purely you.


Comments

Popular posts from this blog

Hatching array of circles in AutoCAD using c# -

ios - UITEXTFIELD InputView Uipicker not working in swift -

Python Pig Latin Translator -