NAME

threadify.rb

SYNOPSIS

enumerable = %w( a b c d )
enumerable.threadify(2){ 'process this block using two worker threads' }
enumerable.threadify(:each_slice, 4){ 'process each slice of 4 in a thread' }

DESCRIPTION

threadify.rb makes it stupid easy to process a bunch of data using 'n'
worker threads

INSTALL

gem install threadify

URI

http://rubyforge.org/projects/codeforpeople
http://github.com/ahoward/threadify/

SAMPLES

<========< sample/a.rb >========>

~ > cat sample/a.rb

  require 'threadify'

  require 'open-uri'
  require 'yaml'

  uris =
    %w(
      http://codeforpeople.com
      http://drawohara.com
      http://twitter.com/drawohara
      http://github.com/ahoward/threadify/
      http://google.com
      http://rubyforge.org
      http://ruby-lang.org
      http://hypem.com
    )

  curl = lambda{|url| open(url){|socket| socket.read}}

  time 'without threadify' do
    uris.each{|uri| curl[uri]}
  end

  time 'with threadify' do
    uris.threadify(uris.size){|uri| curl[uri]}
  end

  BEGIN {
    def time label
      a = Time.now.to_f
      yield
    ensure
      b = Time.now.to_f
      y label => (b - a)
    end
  }

~ > ruby sample/a.rb

  --- 
  without threadify: 8.49043202400208
  --- 
  with threadify: 2.45102596282959

<========< sample/b.rb >========>

~ > cat sample/b.rb

  require 'threadify'

  require 'yaml'

  #size = Integer(ARGV.shift || (2 ** 20))
  size = 64

  haystack = Array.new(size){|i| i}
  needle = 2 * (size / 3) 

  a, b = 4, 2

  time 'without threadify' do
    a =
      haystack.each do |value|
        break value if value == needle
        sleep(rand) # mimic work
      end
  end

  time 'with threadify' do
    b = 
      haystack.threadify(:each_slice, size / 8) do |slice|
        slice.each{|value| threadify! value if value == needle}
        sleep(rand) # mimic work
      end
  end

  raise if a != b

  y :a => a, :b => b, :needle => needle

  BEGIN {
    def time label
      a = Time.now.to_f
      yield
    ensure
      b = Time.now.to_f
      y label => (b - a)
    end
  }

~ > ruby sample/b.rb

  --- 
  without threadify: 19.2692859172821
  --- 
  with threadify: 0.851074934005737
  --- 
  :needle: 42
  :a: 42
  :b: 42

HISTORY

1.4.2
  - fix name collision running under jruby's native threads.  thanks charles nutter!

1.3.0
  - added Threadify(*args, &block) method to execute arbitrary code in parallel

      Threadify(8){ puts Thread.current.object_id }.size #=> 8

1.1.0
  - added ability to specify arbitrary iterator (not only each)
    [0,1,2,3].threadify(:each_slice, 2){|ary| ary}
  - update samples
  - auto include enumerator

0.0.3
  - added ability to short-circuit the parallel processing, a.k.a to 'break'
    from threadify

0.0.2
  - don't use thread.exit, just let the thread die naturally
  - add version to Threadify module
  - comments ;-)