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 ;-)