Word To The Wise This is probably going to be short... But hopefully sweet... But hopefully sweet... Please ask questions... But I don't promise to answer them...
Scheduling Consider the example of 2 sections of code competing for CPU time. One takes 50ms of cpu time The other takes 40ms of blocking something and 10ms of cpu time
Scheduling Run side by side these 2 sections of code would take 100ms in total If we can cooperatively schedule them, we can compress that into just 60ms
What does that do? Creating the fiber does not execute the fiber To kick start the fiber we must `resume` it The first call to resume starts the execution of the fiber's block
What does that do? Once executed the fiber follows normal behaviour Until it reaches `Fiber.yield` Upon which it "returns" the passed parameter Which drops out the resume
Fiber Pool Say we have a blocking operation we want to run concurrently But we only want to do a certain number at the same time Let us invent a pool of worker fibers to do this cooperatively
Fiber Pool add_to_pool first checks to see if the pool is over_capacity? If it is we wait_for_free_pool_space Otherwise we add our fiber into our pool And then we execute it
Fiber Pool wait_for_free_pool_space does two things calls wait_for_next_complete_fiber removes the completed fiber from the pool How does this work? If we look at our new fiber
Fiber Pool Remember that our completion_callback returns our fiber The idea is that when our work has finished it calls our completion_callback Which returns control to the control_fibe Which then pops out the completed fiber to the Fiber.yield in wait_for_next_complete_fiber
Fiber Pool Once we have finished adding work to our pool we need someway to handle the remaining finishing fibers We need to tidy up after ourselves We need to drain the pool
Caveat The EventMachine.run block is why we need the EM.stop command We eventually want to drop out of EventMachine I'm using EventMachine for notifying my fiber pool when my blocking command finishes We could use something else
Fiber Pool We use our convenience method to start our fiber pool We take our created pool and we're going to add 30 tasks Each task is going to be simulating blocking operation by sleeping for 5 seconds When the blocking operation is complete we are going to call the completion_callback
References http://oldmoe.blogspot.com/2008/08/ruby-fibers-vs-ruby-threads.html http://www.igvita.com/2009/05/13/fibers-cooperative-scheduling-in-ruby/ http://pragdave.blogs.pragprog.com/pragdave/2007/12/pipelines-using.html http://pragdave.blogs.pragprog.com/pragdave/2008/01/pipelines-using.html http://www.igvita.com/2010/03/22/untangling-evented-code-with-ruby-fibers/ http://www.igvita.com/2009/05/13/fibers-cooperative-scheduling-in-ruby/ http://github.com/oldmoe/neverblock http://github.com/igrigorik << author of many of the event machine plugins