Pro Yearly is on sale from $80 to $50! »

High In Fiber - ShRUG November 2010

D79fc498d7a5b2ce12180890247476f0?s=47 Jon Rowe
November 08, 2010

High In Fiber - ShRUG November 2010

Presentation on Fibers given to ShRUG in November 2010

D79fc498d7a5b2ce12180890247476f0?s=128

Jon Rowe

November 08, 2010
Tweet

Transcript

  1. High In Fiber ShRUG 8th November 2010 @JonRowe

  2. 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...
  3. High In Fiber? What's a Fiber?

  4. Fibers are... Lightweight Concurrency Control

  5. Fibers are not Threads The only way to do things

  6. Threads vs Fibers Round 1: Fight! Threads have a heavy

    setup cost
  7. Threads vs Fibers http://oldmoe.blogspot.com/2008/08/ruby-fibers-vs-ruby-threads.html

  8. Threads vs Fibers http://oldmoe.blogspot.com/2008/08/ruby-fibers-vs-ruby-threads.html

  9. Threads vs Fibers Ding! Ding! Round 2 Scheduling

  10. Scheduling Threads are scheduled in time slices Controlled by the

    Scheduler
  11. Scheduling Fibers are co-operatively scheduled Controlled by you!

  12. 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
  13. 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
  14. Scheduling http://www.igvita.com/2009/05/13/fibers-cooperative-scheduling-in-ruby/

  15. Example

  16. Example

  17. What does that do Create the fiber and assign it

    a block to execute
  18. What does that do In that block loop forever and

    double x
  19. What does that do Except each iteration we yield x

  20. 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
  21. 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
  22. Example The next call resuming from the yield will hit

    the bottom of the loop and carry on giving us
  23. Example f.resume => 2 f.resume => 4 f.resume => 8

    f.resume => 16
  24. Execution flow

  25. Execution flow $ puts f.resume "Cows" Initial resume value was

    => Cows initial yield value => nil
  26. Execution flow $ puts f.resume "Cats" Then you resumed me

    with Cats second yield value => nil
  27. Execution flow $ puts f.resume "Dogs" Finally you resumed me

    with Dogs => nil
  28. Execution flow $ puts f.resume "Zombies" FiberError: dead fiber called

  29. All Good?

  30. Fiber Pool Ok so lets try a more complex example

  31. 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
  32. Fiber Pool

  33. Fiber Pool pool_size is going to be our concurrency limit

  34. Fiber Pool fibers is going to contain our stack of

    fibers
  35. Fiber Pool control_fiber is going to be our scheduler

  36. Fiber Pool Fiber.current gets the fiber we are currently in

    the execution scope of
  37. Fiber Pool If not specifically declared this is the root

    fiber of ruby itself
  38. Fiber Pool We need some way to add work to

    our pool
  39. Fiber Pool We create a new fiber to wrap our

    work item
  40. Fiber Pool The fiber defines a completion_callback to transfer execution

    control back to the control fiber
  41. Fiber Pool Which passes itself back to the control_fiber

  42. Fiber Pool Our fiber then calls the block with completion_callback

    to perform our work
  43. Fiber Pool Once the fiber is setup We add it

    to the pool The fiber has not yet been run
  44. 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
  45. Fiber Pool

  46. 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
  47. Fiber Pool

  48. 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
  49. Fiber Pool Now we can add fibers to our pool

    Now we need to tidy up some loose ends
  50. Fiber Pool

  51. Fiber Pool

  52. Fiber Pool

  53. Fiber Pool fibers_left_to_process? we haven't used that anywhere? In order

    to actually use our pool we need one more method
  54. Fiber Pool

  55. 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
  56. Fiber Pool

  57. Fiber Pool All we are doing here is checking if

    there are fibers still ticking And waiting until they are finished
  58. Fiber Pool Now we can use our fiber pool But

    it will need some setup So lets make a convenience wrapper
  59. Fiber Pool

  60. Fiber Pool We create the fiber which is to be

    our control_fiber We create a new pool We yield that pool to whatever code we are setting up
  61. Fiber Pool We drain the pool We cheat and call

    EM.stop, I'll cover that in a bit We immediately execute our fiber
  62. Fiber Pool Let’s use the pool

  63. Fiber Pool

  64. 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
  65. Fiber Pool

  66. 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
  67. The result? For comparison lets look at it conventionally first

  68. The result?

  69. The result?

  70. The result? What should have taken 150 seconds Has taken

    15 seconds
  71. EventMachine? Where did that come from?

  72. EventMachine? Fibers are cooperatively scheduled That doesn't make them instantly

    intelligent We need something to wake them up appropriately
  73. EventMachine? I'm using EventMachine out of convenience It could be

    any control structure that can call f.resume
  74. Evented IO Ideally I'd like to wake my fibers up

    directly upon receiving a message Then I don't have to have extra overhead
  75. 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
  76. Fin

  77. Questions?

  78. Pub!