$30 off During Our Annual Pro Sale. View Details »

How to write synchronization mechanisms for Fiber (RubySapporo.beam)

How to write synchronization mechanisms for Fiber (RubySapporo.beam)

RubySapporo.beam #3 edition.

seki at druby.org

October 21, 2017
Tweet

More Decks by seki at druby.org

Other Decks in Programming

Transcript

  1. ͠͹Β͓͘଴͍ͪͩ͘͞
    ✓ ͝ཡͷεϙϯαʔͷఏڙ
    ʹΑΓ͓ૹΓ͠·͢

    View Slide

  2. slide sponsors
    Rails !!
    @mame
    Kent Beck
    @hisashim
    Ember.Sapporo @tricknotes

    View Slide

  3. slide sponsors
    Ruby @iwadon
    OSS Gate @ktou
    dRuby Web ( eBook Store) http://
    estore.ohmsha.co.jp/titles/978427406609P @hisashim
    @m_seki "re: "
    @awazeki
    Mastodon Pawoo Ruby @pixiv
    m_seki
    @tsuboi
    07 smalruby @vestige_

    View Slide

  4. How to write
    synchronization mechanisms
    for Fiber
    [email protected]
    RubySapporo.beam#3

    View Slide

  5. @m_seki
    Ruby
    ERB, dRuby, Rinda
    ࠷ۙͷcommit: ERBϝϯςφʹk0kubun͞ΜΛadd

    View Slide

  6. ΤοηΠ2ຊࡌͤͨʂ
    ਺ਓ͔Β࣭໰͋Γ·͕ͨ͠ݪߘྉ͸1ຊ෼Ͱ͢

    View Slide

  7. 2005 - ·ͩॳ࡮Γങ͑·͢
    dRuby
    ʹΑΔ
    ؔকढ़ஶ
    ෼ࢄ
    ɾ
    Web
    ϓϩάϥϛϯά
    12प೥

    View Slide

  8. 2012 (-2014 ઈ൛)
    2೥Ͱઈ൛

    View Slide

  9. 2017 re-published on the web
    CC by SAͳͷͰ࿨༁Ͱ͖ΔΑ?

    View Slide

  10. Agenda
    Fiber
    Fiber
    Enumerator
    Synchronize
    Multiplexer

    View Slide

  11. Fiberͷ͓͞Β͍
    Process
    Thread
    Fiber
    ࡾͭͷ࣮ߦओମͷҧ͍͔Βߟ͑Δ

    View Slide

  12. Process ↔ Thread ↔ Fiber
    Process
    Thread
    Fiber
    ͦͷٕज़͸ద੾ͳͷʁ

    View Slide

  13. Process
    ಌΕ͍ͯͨࠒͷ࿩

    View Slide

  14. Before Process
    Key
    https://www.youtube.com/watch?v=TOnS97C-RGQ

    View Slide

  15. Before Process (80s)
    OS
    PC
    BREAKΩʔ΋ϙʔϦϯά

    View Slide

  16. ϓϩηε΁ͷಌΕ

    View Slide

  17. View Slide

  18. Before Process (90s)
    Fiber
    Macintoshͷෆ҆ఆ͞͸ϓϩηε͕͋Ε͹ղܾ͢Δͱ
    ݴΘΕͯͨ

    View Slide

  19. ࣮ࡍͷγεςϜ
    ..
    ֎෦ͱͷ΍ΓͱΓ͸ආ͚ΒΕͳ͍͠෭࡞༻͸ඞཁ

    View Slide

  20. Processes
    େࣄͳ͜ͱͳͷͰೋ౓ݴ͍·ͨ͠

    View Slide

  21. ProcessͰॻ͘ͱ͖ͷؾ࣋ͪ

    View Slide

  22. ProcessͰॻ͘ͱ͖ͷؾ࣋ͪ
    Skip!

    View Slide

  23. IPC͸ΊΜͲ͍͘͞
    pipe
    SystemV IPC
    socket
    ͦΕͧΕಛ௃͕͋Γɺ࢖ͬͯΈͯΘ͔ΔΊΜͲ͘
    ͕͋͞͞Δ

    View Slide

  24. Thread
    1ϓϩηεͰίΞΛ࢖͍੾Βͳͯ͘΋͍͍͡ΌΜ

    View Slide

  25. ThreadͰॻ͘ͱ͖ͷؾ࣋ͪ

    ݟ͑Δ͚Ͳ৮Βͳ͍Ϟϥϧ

    View Slide

  26. Threadʹඞཁͳၗຫ͞
    OS
    OS

    View Slide

  27. Fiber
    Thread
    Thread
    Thread
    mrubyʹ͸Threadͳ͍͔ΒFiberҰ୒

    View Slide

  28. Fiberʹඞཁͳࣗ৴
    Ruby

    View Slide

  29. FiberͰॻ͘ͱ͖ͷؾ࣋ͪ
    ...
    Fiber
    ఆੴΛݟ͚ͭΔ·Ͱ͕͍ͨ΁Μ

    View Slide

  30. Process ↔ Thread ↔ Fiber
    Process
    Thread
    Fiber

    View Slide

  31. Process ↔ Thread ↔ Fiber
    Fiber
    Thread
    Process
    ͋ͳͨ͸ͳʹΛ࢖͏΂͖ʁ

    View Slide

  32. ͠͹Β͓͘଴͍ͪͩ͘͞
    ✓ ෼͘Β͍͔ͳ
    ✓ 1SPDFTT 5ISFBE 'JCFS
    ✓ ࣍͸'JCFSΛקΊΔΑʂ

    View Slide

  33. ͳͥFiberͷ࿩Λ͢Δͷ͔
    Fiber
    EventMachine͍ͬͯ͢͝@tricknotesʹڭΘͬͨΑ͏ͳ...

    View Slide

  34. ͳͥFiberͷ࿩Λ͢Δͷ͔
    X11 GUI socket
    1
    Fiber͕͋Δͱॻ͖΍͘͢ͳΔ΋ͷΛΑ͘ॻ͍ͯͨ

    View Slide

  35. ͳͥFiberͷ࿩Λ͢Δͷ͔
    Thread

    View Slide

  36. Fiberೖ໳
    Fibonacci Enumerator
    Rdv SizedQueue, channel
    Multiplexer
    3ͭͷςʔϚͰઆ໌͠·͢

    View Slide

  37. ࠷ॳͷςʔϚ
    Enumerator
    Fiber API
    Fiber
    Enumertor

    View Slide

  38. Α͋͘ΔFibonacci
    [0, 1]
    [1, 1]
    [2, 2]
    [3, 3]
    [4, 5]
    [5, 8]
    [6, 13]
    [7, 21]
    [8, 34]
    [9, 55]
    ్தͷ஋Λฦ͢ͷ͕೉͍͠
    def fibonacci(n)
    a, b = 1, 1
    n.times do |i|
    p [i, a]
    a, b = b, a + b
    end
    end
    fibonacci(10)

    View Slide

  39. FiberͰॻ͖௚͢
    API
    fib = Fiber.new do
    a, b = 1, 1
    while true
    Fiber.yield(a)
    a, b = b, a + b
    end
    end
    10.times do |n|
    p [n, fib.resume]
    end
    def fibonacci(n)
    a, b = 1, 1
    n.times do |i|
    p [i, a]
    a, b = b, a + b
    end
    end
    fibonacci(10)
    FiberΛ࢖͏ͱ్தܦաͷ஋ΛฦͤΔ

    View Slide

  40. API
    Fiber.new
    Fiber#resume
    Fiber.yield

    View Slide

  41. Fiber.new
    Fiber
    fib = Fiber.new do
    a, b = 1, 1
    while true
    Fiber.yield(a)
    a, b = b, a + b
    end
    end
    10.times do |n|
    p [n, fib.resume]
    end
    Fiber࡞͚ͬͨͩ

    View Slide

  42. Fiber#resume
    Fiber
    fib = Fiber.new do
    a, b = 1, 1
    while true
    Fiber.yield(a)
    a, b = b, a + b
    end
    end
    10.times do |n|
    p [n, fib.resume]
    end
    FiberʹͳΓ͖ͬͯಈ͘

    View Slide

  43. Fiber.yield
    resume Fiber
    resume
    fib = Fiber.new do
    a, b = 1, 1
    while true
    Fiber.yield(a)
    a, b = b, a + b
    end
    end
    10.times do |n|
    p [n, fib.resume]
    end
    resumeʹ໭Δ

    View Slide

  44. resume, again
    resume yield
    fib = Fiber.new do
    a, b = 1, 1
    while true
    Fiber.yield(a)
    a, b = b, a + b
    end
    end
    10.times do |n|
    p [n, fib.resume]
    end

    View Slide

  45. resumeͷߦ͖ઌ
    Fiber new
    resume Fiber
    Fiber.yield
    resume ...

    View Slide

  46. APIΛઆ໌ͨ͠
    resume yield

    View Slide

  47. EnumeratorͰॻ͖௚͢
    fib = Fiber.new do
    a, b = 1, 1
    while true
    Fiber.yield(a)
    a, b = b, a + b
    end
    end
    10.times do |n|
    p [n, fib.resume]
    end
    def fibonacci
    a, b = 1, 1
    while true
    yield(a)
    a, b = b, a + b
    end
    end
    fib = to_enum(:fibonacci)
    10.times do |n|
    p [n, fib.next]
    end

    View Slide

  48. Enumerator
    ❌ Fiber

    View Slide

  49. ͠͹Β͓͘଴͍ͪͩ͘͞
    ✓ &OVNFSBUPSͰ"1*Λઆ໌
    ✓ ೉ָ͕͠͞͠Ίͳ͍
    ✓ ࣍͸3EW

    View Slide

  50. ࣍ͷςʔϚ

    View Slide

  51. QueueΛհͨ͠ڠௐ
    Queue Thread
    Thread
    q = SizedQueue.new(1)
    Thread.new do
    10.times do |n|
    sleep(rand)
    q.push(n)
    p [:push, n]
    end
    end
    Thread.new do
    10.times do |n|
    sleep(rand)
    p [:pop, q.pop]
    end
    end.join

    View Slide

  52. ͜ΕͷFiber൛
    Rdv Fiber
    rendez-vous
    rdv = Rdv.new
    Fiber.new do
    10.times do |n|
    rdv.push(n)
    p [:push, n]
    end
    end.resume
    Fiber.new do
    10.times do |n|
    p [:pop, rdv.pop]
    end
    end.resume

    View Slide

  53. rendez-vous


    rendez-vous

    View Slide

  54. ड͚औΔଆ͕଴ͭ৔߹


    rendez-vous

    View Slide

  55. ͜͏͍͏৔߹΋͋Δ





    rendez-vous
    ΋ͪΖΜٯ΋͋Δ

    View Slide

  56. Rdvͷ࣮૷
    initialize
    push
    pop
    def initialize
    @reader = []
    @writer = []
    end
    def push(it)
    if @reader.empty?
    @writer << [it, Fiber.current]
    return Fiber.yield
    end
    @reader.shift.resume(it)
    end
    def pop
    if @writer.empty?
    @reader << Fiber.current
    return Fiber.yield
    end
    value, fiber = @writer.shift
    fiber.resume
    return value
    end

    View Slide

  57. ࠷ۙ޷͖ͳΠσΟΦϜ
    resume
    yield

    View Slide

  58. ͱΓ͋͑ͣresume
    Fiber.new resume
    Thread.new
    resume

    View Slide

  59. initialize
    @reader pop @writer push
    Fiber
    def initialize
    @reader = []
    @writer = []
    end
    def push(it)
    if @reader.empty?
    @writer << [it, Fiber.current]
    return Fiber.yield
    end
    @reader.shift.resume(it)
    end
    def pop
    if @writer.empty?
    @reader << Fiber.current
    return Fiber.yield
    end
    value, fiber = @writer.shift
    fiber.resume
    return value
    end

    View Slide

  60. push
    @reader
    (yield)
    @reader (resume)
    def initialize
    @reader = []
    @writer = []
    end
    def push(it)
    if @reader.empty?
    @writer << [it, Fiber.current]
    return Fiber.yield
    end
    @reader.shift.resume(it)
    end
    def pop
    if @writer.empty?
    @reader << Fiber.current
    return Fiber.yield
    end
    value, fiber = @writer.shift
    fiber.resume
    return value
    end

    View Slide

  61. @reader͕͍ͳ͍
    Fiber.current yield
    def initialize
    @reader = []
    @writer = []
    end
    def push(it)
    if @reader.empty?
    @writer << [it, Fiber.current]
    return Fiber.yield
    end
    @reader.shift.resume(it)
    end
    def pop
    if @writer.empty?
    @reader << Fiber.current
    return Fiber.yield
    end
    value, fiber = @writer.shift
    fiber.resume
    return value
    end

    View Slide

  62. @reader͕͍Δ
    @reader resume
    pop Fiber
    def initialize
    @reader = []
    @writer = []
    end
    def push(it)
    if @reader.empty?
    @writer << [it, Fiber.current]
    return Fiber.yield
    end
    @reader.shift.resume(it)
    end
    def pop
    if @writer.empty?
    @reader << Fiber.current
    return Fiber.yield
    end
    value, fiber = @writer.shift
    fiber.resume
    return value
    end

    View Slide

  63. pop
    @writer
    (yield)
    @writer (resume)
    def initialize
    @reader = []
    @writer = []
    end
    def push(it)
    if @reader.empty?
    @writer << [it, Fiber.current]
    return Fiber.yield
    end
    @reader.shift.resume(it)
    end
    def pop
    if @writer.empty?
    @reader << Fiber.current
    return Fiber.yield
    end
    value, fiber = @writer.shift
    fiber.resume
    return value
    end
    pushͱҰॹͩΑʂ
    Skip!

    View Slide

  64. @writer͕͍ͳ͍
    Fiber.current yield
    def initialize
    @reader = []
    @writer = []
    end
    def push(it)
    if @reader.empty?
    @writer << [it, Fiber.current]
    return Fiber.yield
    end
    @reader.shift.resume(it)
    end
    def pop
    if @writer.empty?
    @reader << Fiber.current
    return Fiber.yield
    end
    value, fiber = @writer.shift
    fiber.resume
    return value
    end
    Skip!

    View Slide

  65. @writer͕͍Δ
    @writer resume
    push Fiber
    def initialize
    @reader = []
    @writer = []
    end
    def push(it)
    if @reader.empty?
    @writer << [it, Fiber.current]
    return Fiber.yield
    end
    @reader.shift.resume(it)
    end
    def pop
    if @writer.empty?
    @reader << Fiber.current
    return Fiber.yield
    end
    value, fiber = @writer.shift
    fiber.resume
    return value
    end
    Skip!

    View Slide

  66. ݕࠪதͷഉଞ੍ޚ
    Fiber
    Thread
    def initialize
    @reader = []
    @writer = []
    end
    def push(it)
    if @reader.empty?
    @writer << [it, Fiber.current]
    return Fiber.yield
    end
    @reader.shift.resume(it)
    end
    def pop
    if @writer.empty?
    @reader << Fiber.current
    return Fiber.yield
    end
    value, fiber = @writer.shift
    fiber.resume
    return value
    end
    Thread೴ͷਓ͸υΩυΩͯ͠Δͱࢥ͏

    View Slide

  67. Threadͱͷҧ͍
    Thread
    Monitor

    View Slide

  68. ͏༷͘͝ࢠ
    rdv = Rdv.new
    Fiber.new do
    10.times do |n|
    rdv.push(n)
    p [:push, n]
    end
    end.resume
    Fiber.new do
    10.times do |n|
    p [:pop, rdv.pop]
    end
    end.resume
    Fiber.newした

    kara-matzを召喚

    View Slide

  69. ͏༷͘͝ࢠ
    rdv = Rdv.new
    Fiber.new do
    10.times do |n|
    rdv.push(n)
    p [:push, n]
    end
    end.resume
    Fiber.new do
    10.times do |n|
    p [:pop, rdv.pop]
    end
    end.resume
    kara-matzをresume

    kara-matzのターン


    View Slide

  70. ͏༷͘͝ࢠ
    rdv = Rdv.new
    Fiber.new do
    10.times do |n|
    rdv.push(n)
    p [:push, n]
    end
    end.resume
    Fiber.new do
    10.times do |n|
    p [:pop, rdv.pop]
    end
    end.resume
    kara-matzのpush!

    相手がいない。

    自分とデータをメモしyield。ターン終了

    View Slide

  71. ͏༷͘͝ࢠ
    rdv = Rdv.new
    Fiber.new do
    10.times do |n|
    rdv.push(n)
    p [:push, n]
    end
    end.resume
    Fiber.new do
    10.times do |n|
    p [:pop, rdv.pop]
    end
    end.resume
    メインのターン

    Fiber.new

    ichi-matzを召喚

    View Slide

  72. ͏༷͘͝ࢠ
    rdv = Rdv.new
    Fiber.new do
    10.times do |n|
    rdv.push(n)
    p [:push, n]
    end
    end.resume
    Fiber.new do
    10.times do |n|
    p [:pop, rdv.pop]
    end
    end.resume
    ichi-matzをresume

    ichi-matzのターン


    View Slide

  73. ͏༷͘͝ࢠ
    rdv = Rdv.new
    Fiber.new do
    10.times do |n|
    rdv.push(n)
    p [:push, n]
    end
    end.resume
    Fiber.new do
    10.times do |n|
    p [:pop, rdv.pop]
    end
    end.resume
    ichi-matzのpop!

    ichi-matzはメモを読んだ

    データを手にいれた。kara-matzをresumeしターン終了

    View Slide

  74. ͏༷͘͝ࢠ
    rdv = Rdv.new
    Fiber.new do
    10.times do |n|
    rdv.push(n)
    p [:push, n]
    end
    end.resume
    Fiber.new do
    10.times do |n|
    p [:pop, rdv.pop]
    end
    end.resume
    kara-matzのpush!

    相手がいない。

    自分とデータをメモしyield。ターン終了

    View Slide

  75. ͏༷͘͝ࢠ
    rdv = Rdv.new
    Fiber.new do
    10.times do |n|
    rdv.push(n)
    p [:push, n]
    end
    end.resume
    Fiber.new do
    10.times do |n|
    p [:pop, rdv.pop]
    end
    end.resume
    ichi-matzのpop!

    ichi-matzはメモを読んだ

    データを手にいれた。kara-matzをresumeしターン終了
    Skip!

    View Slide

  76. 10
    Skip!

    View Slide

  77. ͏༷͘͝ࢠ
    rdv = Rdv.new
    Fiber.new do
    10.times do |n|
    rdv.push(n)
    p [:push, n]
    end
    end.resume
    Fiber.new do
    10.times do |n|
    p [:pop, rdv.pop]
    end
    end.resume
    ichi-matzはしんでしまった

    メインのターン

    メインはしんでしまった
    Skip!

    View Slide

  78. ͏͖ͦ͝͏ʂ
    ͕͢͞

    View Slide

  79. ͜͜ͷ·ͱΊ
    Fiber
    resume
    yield

    View Slide

  80. ͜͜ͷ·ͱΊ
    Thread
    Thread Fiber
    ޿ౡͰ͸@_ko1͔ΒAutoFiberͱ͍͏ఏҊΛ঺հͯ͠
    ͍ͨɻϒϩοΫͦ͠͏ʹͳͬͨΒࣗಈతʹίϯς
    Ωετ੾Γସ͑͢ΔFiberɻ͜͜͸ͦΕ΁ͷճ౴

    View Slide

  81. ͠͹Β͓͘଴͍ͪͩ͘͞
    ✓ 'JCFSͷಉظͷ࣮૷
    ✓ 3EW
    ✓ ࣍͸ιέοτϓϩάϥϛ
    ϯά

    View Slide

  82. ࣍ͷςʔϚ
    socket

    View Slide

  83. ͢͢Ί͔ͨ
    dRuby
    Thread
    Thread Fiber

    View Slide

  84. ૉ๿͚ͩͲҰ్
    I/O
    1
    def main_loop
    loop do
    select
    fds.each do |fd|
    call_callback
    end
    end
    end
    def on_accept
    c = accept
    loop do
    read_request(c)
    do_it
    write_response(c)
    end
    end
    def read_n(fd, sz)
    ...
    ...
    end

    View Slide

  85. Thread൛
    fd Thread
    def main_loop
    loop do
    select
    fds.each do |fd|
    call_callback
    end
    end
    end
    def on_accept
    c = accept
    Thread.new(c) do |fd|
    loop do
    read_request(fd)
    do_it
    write_response(fd)
    end
    end
    end
    def read_n(fd, sz)
    ...
    ...
    end
    ௥Ճ͸͚ͩ͜͜
    ௥Ճ͸͚ͩ͜͜

    View Slide

  86. Fiber൛
    def main_loop
    loop do
    select
    fds.each do |fd|
    call_callback
    end
    end
    end
    def on_accept
    c = accept
    Fiber.new do
    loop do
    read_request(c)
    do_it
    write_response(c)
    end
    end.resume
    end
    def read_n(fd, sz)
    ...
    ...
    end
    Swapped
    with Fiber

    View Slide

  87. Fiber൛վ
    I/O
    I/O
    def main_loop
    loop do
    select
    fds.each do |fd|
    call_callback
    end
    end
    end
    def on_accept
    c = accept
    Fiber.new do
    loop do
    read_request(c)
    do_it
    write_response(c)
    end
    end.resume
    end
    def read_n(fd, sz)
    ...
    fd.read_nonblock(sz)
    rescue WaitReadable
    Fiber.yield
    retry
    end

    View Slide

  88. Block-ish non-block I/O
    Fiber.yield
    main_loop
    resume
    def main_loop
    loop do
    select
    fds.each do |fd|
    call_callback
    end
    end
    end
    def on_accept
    c = accept
    Fiber.new do
    loop do
    read_request(c)
    do_it
    write_response(c)
    end
    end.resume
    end
    def read_n(fd, sz)
    ...
    fd.read_nonblock(sz)
    rescue WaitReadable
    Fiber.yield
    retry
    end

    View Slide

  89. ίʔϧόοΫͰresume

    View Slide

  90. Bartender
    fd readable, writable
    https://github.com/seki/bartender

    View Slide

  91. Bartender::Context
    readable, writable
    block-ish non-block I/O
    Context#[]=(event, fd, callback)
    Πϕϯτछʢ:read, :writeʣͱfdͷ૊ʹίʔϧόοΫΛొ࿥

    View Slide

  92. _read()
    read_nonblock
    readable retry
    Fiber
    def _read(fd, sz)
    return fd.read_nonblock(sz)
    rescue IO::WaitReadable
    wait_readable(fd)
    retry
    end
    def wait_readable(fd); wait_io(:read, fd); end
    def wait_io(event, fd)
    self[event, fd] = Fiber.current.method(:resume)
    Fiber.yield
    ensure
    delete(event, fd)
    end

    View Slide

  93. read_nonblock
    sz
    IO::WaitReadable
    def _read(fd, sz)
    return fd.read_nonblock(sz)
    rescue IO::WaitReadable
    wait_readable(fd)
    retry
    end
    def wait_readable(fd); wait_io(:read, fd); end
    def wait_io(event, fd)
    self[event, fd] = Fiber.current.method(:resume)
    Fiber.yield
    ensure
    delete(event, fd)
    end

    View Slide

  94. wait_io()
    resume
    Fiber.yield
    select
    resume readable
    def _read(fd, sz)
    return fd.read_nonblock(sz)
    rescue IO::WaitReadable
    wait_readable(fd)
    retry
    end
    def wait_readable(fd); wait_io(:read, fd); end
    def wait_io(event, fd)
    self[event, fd] = Fiber.current.method(:resume)
    Fiber.yield
    ensure
    delete(event, fd)
    end

    View Slide

  95. I'll show this to you on an actual application

    View Slide

  96. tiny_drbͷൈਮ
    read
    def req_drb(reader)
    ref = load(reader, false)
    msg = load(reader)
    argc = load(reader)
    argv = argc.times.collect {load(reader)}
    block = load(reader, false)
    [ref, msg, argv]
    end
    def load(reader, marshal=true)
    sz = reader.read(4)
    sz = sz.unpack('N')[0]
    data = reader.read(sz)
    return data unless marshal
    begin
    Marshal.load(data)
    rescue
    DRb::DRbUnknown.new($!, data)
    end
    end

    View Slide

  97. צҧ͍
    ❌ readable
    ❌ writable

    View Slide

  98. ੲΑ͘ݟͨόά
    select()

    View Slide

  99. σϞʢ͸͋Γ·ͤΜʣ
    sample
    ...
    ...

    View Slide

  100. tiny_drb.rb
    irb -r drb irb -r drb
    tiny_drb.rb
    Rdv
    https://github.com/seki/bartender/tree/master/sample
    Skip!

    View Slide

  101. tiny_drbͷ͓΋͠Ζ͍ͱ͜Ζ
    block-ish nonblock I/O
    Fiber select
    Rdv

    View Slide

  102. ଞʹࢼ࡞ͨ͠΋ͷ
    Fiber Rinda::TupleSpace
    Fiber WEBrick
    FD Thread
    Skip!

    View Slide

  103. Threadͱͷ଴ͪ߹Θͤ
    Thread.value
    IO.pipe close
    class ThreadTask
    def initialize(*args, &block)
    left, @right = IO.pipe
    @task = Thread.new do
    begin
    block.call(*args)
    ensure
    left.close
    end
    end
    end
    def value
    if @right
    Bartender.wait_readable(@right)
    @right.close
    end
    @task.value
    ensure
    @right = nil
    end
    end
    Skip!

    View Slide

  104. Multiplexerͷ·ͱΊ
    vs
    Thread
    Fiber
    block-ish non-block I/O

    View Slide

  105. Fiberೖ໳ͷ·ͱΊ
    Fibonacci Enumerator
    Rdv SizedQueue, channel
    Multiplexer

    View Slide

  106. ͠͹Β͓͘଴͍ͪͩ͘͞
    ✓ ࣌ؒ͋Δ͔ͳʁ
    ✓ ͓·͚

    View Slide

  107. ͓·͚
    Fiber
    ...
    Skip?

    View Slide

  108. ࠓճͷྫ͸

    View Slide


  109. Fiber
    Thread FiberError
    gem

    View Slide

  110. ͭ·Γ
    Fiber
    ࢖༻͢Δgemͷ࢓૊Έ͘Β͍Θ͔ͬͯͳ͍ͱ

    View Slide

  111. ϋϚΔྫ
    Fiber Twitter
    JSON.parse
    String
    JSON.parse

    View Slide

  112. ϋϚΓͦ͏ͳྫ
    RDBMS ...

    View Slide

  113. ͠͹Β͓͘଴͍ͪͩ͘͞
    ✓ ͓ΘΓ

    View Slide

  114. ·ͱΊ
    Thread Fiber
    Fiber API I/O

    View Slide

  115. Process ↔ Thread ↔ Fiber
    Fiber
    Thread
    Process
    ͋ͳͨ͸ͳʹΛ࢖͏΂͖ʁ

    View Slide

  116. ϓϩάϥϛϯάErlangΑΓ
    -module(kvs).
    -export([start/0, store/2, lookup/1]).
    start() -> register(kvs, spawn(fun() ->
    loop() end)).
    store(Key, Value) -> rpc({store, Key,
    Value}).
    lookup(Key) -> rpc({lookup, Key}).
    rpc(Q) ->
    kvs ! {self(), Q},
    receive
    {kvs, Reply} ->
    Reply
    end.
    loop() ->
    receive
    {From, {store, Key, Value}} ->
    put(Key, {ok, Value}),
    From ! {kvs, true},
    loop();
    {From, {lookup, Key}} ->
    From ! {kvs, get(Key)},
    loop()
    end.

    View Slide

  117. serverͷϝΠϯϧʔϓ
    -module(kvs).
    -export([start/0, store/2, lookup/1]).
    start() -> register(kvs, spawn(fun() ->
    loop() end)).
    store(Key, Value) -> rpc({store, Key,
    Value}).
    lookup(Key) -> rpc({lookup, Key}).
    rpc(Q) ->
    kvs ! {self(), Q},
    receive
    {kvs, Reply} ->
    Reply
    end.
    loop() ->
    receive
    {From, {store, Key, Value}} ->
    put(Key, {ok, Value}),
    From ! {kvs, true},
    loop();
    {From, {lookup, Key}} ->
    From ! {kvs, get(Key)},
    loop()
    end.
    server main loop

    View Slide

  118. client͸ࡶʹϒϩοΫ
    x
    -module(kvs).
    -export([start/0, store/2, lookup/1]).
    start() -> register(kvs, spawn(fun() ->
    loop() end)).
    store(Key, Value) -> rpc({store, Key,
    Value}).
    lookup(Key) -> rpc({lookup, Key}).
    rpc(Q) ->
    kvs ! {self(), Q},
    receive
    {kvs, Reply} ->
    Reply
    end.
    loop() ->
    receive
    {From, {store, Key, Value}} ->
    put(Key, {ok, Value}),
    From ! {kvs, true},
    loop();
    {From, {lookup, Key}} ->
    From ! {kvs, get(Key)},
    loop()
    end.
    client API

    View Slide

  119. ΋͜͠Εਅࣅͯ͠Δͱ
    x
    -module(kvs).
    -export([start/0, store/2, lookup/1]).
    start() -> register(kvs, spawn(fun() ->
    loop() end)).
    store(Key, Value) -> rpc({store, Key,
    Value}).
    lookup(Key) -> rpc({lookup, Key}).
    rpc(Q) ->
    kvs ! {self(), Q},
    receive
    {kvs, Reply} ->
    Reply
    end.
    loop() ->
    receive
    {From, {store, Key, Value}} ->
    put(Key, {ok, Value}),
    From ! {kvs, true},
    loop();
    {From, {lookup, Key}} ->
    From ! {kvs, get(Key)},
    loop()
    end.
    serverͷओॲཧͰrpcΛ
    ݺΜͩΒݻ·Δ͔΋...

    View Slide

  120. 2छྨͷϝοηʔδΛѻ͏
    1. Receive
    4. Do it
    2. Send task1
    3. Receive task1
    5. Send
    receive
    2種類のメッセージ

    View Slide

  121. ͋ͱͰ΍ΔϦετ
    1. Receive
    4. Do it
    2. Send task1
    3. Receive task1
    5. Send
    処理できないやつをあとでやる

    View Slide

  122. ͋ͱͰ΍Δ࡞ઓ...
    ࣗ෼ͷ౎߹ͷྑ͍࣌ʹ΍ΔΑ
    ΍Γ͔͚ͷ͕ऴΘ͔ͬͯΒ࣍ͷཁٻΛ΍Δ
    ࣗ෼͸͏·͘ߦ͘

    View Slide

  123. ૬ޓʹґଘ͢Δ෦෼͕͋ͬͨΒ...
    ݏͳ༧ײ͕͢Δ

    View Slide

  124. "͋ͱͰ΍Δ"Λ࣋ͬͨ··͓ޓ͍ʹreplyΛ଴ͬͪΌ͏
    ݏͳ༧ײ͕͢Δ

    View Slide

  125. 20ੈل
    ػೳ෼ࢄ
    ͜ͷόά΍ͬͨ͜ͱ͋Δ

    View Slide

  126. Ӆ͞Εͨґଘ͕͋ͬͨ
    ࣌ʑɺΈΜͳ͕reply଴ͪʹͳΔ
    ୭΋ࢭ·ͬͯͳ͍͚ͲγεςϜ͸ࢭ·ͬͯΔ

    View Slide