Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Play with ruby threads

Play with ruby threads

Damien Mathieu

February 12, 2014
Tweet

More Decks by Damien Mathieu

Other Decks in Programming

Transcript

  1. Play with Ruby Threads

    View full-size slide

  2. Ruby Program
    Fetch URL A
    Fetch URL B
    End Program

    View full-size slide

  3. Ruby Program
    Fetch URL A Fetch URL B
    End Program

    View full-size slide

  4. require 'net/http'
    !
    t1 = Thread.new {
    !
    content = Net::HTTP.get(URI.parse("http://google.com"))
    puts "I just fetched google.com"
    }
    !
    t2 = Thread.new {
    !
    content = Net::HTTP.get(URI.parse("http://github.com"))
    puts "I just fetched github.com"
    }
    !
    t1.join && t2.join
    puts "I've finished executing everything"

    View full-size slide

  5. › time ruby threads.rb!
    I just fetched google.com!
    I just fetched github.com!
    I've finished executing everything!
    ruby threads.rb 0.13s user 0.06s system 40% cpu 0.450 total

    View full-size slide

  6. require 'net/http'
    !
    content = Net::HTTP.get(URI.parse("http://google.com"))
    puts "I just fetched google.com"
    !
    content = Net::HTTP.get(URI.parse("http://github.com"))
    puts "I just fetched github.com"
    !
    puts "I've finished executing everything"

    View full-size slide

  7. time ruby no_threads.rb!
    I just fetched google.com!
    I just fetched github.com!
    I've finished executing everything!
    ruby no_thread.rb 0.12s user 0.06s system 6% cpu 2.698 total

    View full-size slide

  8. 2.698
    0.450
    5.99

    View full-size slide

  9. Lifecycle of a thread

    View full-size slide

  10. Thread.new
    • Thread.new { … }!
    • Thread.fork { … }!
    • Thread.start(1, 2) { |x, y| … }

    View full-size slide

  11. Thread#join
    thread = Thread.new { sleep 3 }
    thread.join

    View full-size slide

  12. Thread#value
    thread = Thread.new do
    400 + 5
    end
    puts thread.value #=> 405

    View full-size slide

  13. Thread#status
    thread = Thread.new do
    Thread.current.status #=> 'run'
    2 * 3
    end
    puts thread.status #=> 'run'
    thread.join
    puts thread.status #=> false

    View full-size slide

  14. Thread#stop
    thread = Thread.new do
    Thread.stop
    puts 'Hello there'
    end
    !
    # wait for the thread to trigger its stop
    nil until thread.status == 'sleep'
    thread.wakeup
    thread.join

    View full-size slide

  15. Thread Safety

    View full-size slide

  16. Non-deterministic
    context switching
    • In order to provide fair access, the thread
    scheduler can pause a thread at any time

    View full-size slide

  17. Non-deterministic
    context switching
    class Post
    !
    def comments
    @comments ||= []
    end
    end

    View full-size slide

  18. Non-deterministic
    context switching
    class Post
    !
    def comments
    if @comments.nil?
    temp = []
    @comments = temp
    end
    end
    end

    View full-size slide

  19. Non-deterministic
    context switching
    class Post
    def initialize
    @comments_mutex = Mutex.new
    end
    !
    def comments
    @comments_mutex.synchronize do
    @comments ||= []
    end
    end
    end

    View full-size slide

  20. MRI’s GIL
    MRI has something called a global interpreter lock (GIL).!
    It's a lock around the execution of Ruby code.!
    This means that in a multi-threaded context, only one thread
    can execute Ruby code at any one time.

    View full-size slide

  21. MRI’s GIL
    So if you have 8 threads busily working on a 8-core machine,
    only one thread and one core will be busy at any given time.!
    The GIL exists to protect Ruby internals from race conditions
    that could corrupt data.!
    There are caveats and optimizations, but this is the gist.

    View full-size slide

  22. How many threads
    should I use?
    • Is your program IO or CPU bound?!
    • IO Bound will allow a lot of threads!
    • CPU Bound will depend of the number of cores!
    • The only way is to measure

    View full-size slide

  23. http://ruby-doc.org/
    core-2.1.0/Thread.html

    View full-size slide

  24. http://bit.ly/ruby-threads

    View full-size slide