Skip to content

Instantly share code, notes, and snippets.

@parrish
Created February 26, 2012 01:02
Show Gist options
  • Save parrish/1911991 to your computer and use it in GitHub Desktop.
Save parrish/1911991 to your computer and use it in GitHub Desktop.
DeferredProxy
require 'thread'
require 'fiber'
require 'benchmark'
include Benchmark
class DeferredProxy < BasicObject
def initialize(&block)
@fiber = ::Fiber.new do
thread = ::Thread.new{ @result = block.call }
::Fiber.yield
thread.join
end
@fiber.resume
end
def method_missing(method, *args, &block)
@fiber.resume unless @result
@result.send method, *args, &block
end
end
def slow_method(name, number)
puts "starting #{ name }\n"
sleep rand + rand(5)
puts "#{ name } done\n"
[number, number + 1]
end
def combine(label, first, second)
hash = Hash[ *first.zip(second).flatten ]
puts "\t#{ label }: #{ hash.inspect }"
end
a = DeferredProxy.new { slow_method 'a', 1 }
b = DeferredProxy.new { slow_method 'b', 3 }
c = DeferredProxy.new { slow_method 'c', 5 }
d = DeferredProxy.new { slow_method 'd', 7 }
e = DeferredProxy.new { slow_method 'e', 9 }
combine 'a, b', a, b
combine 'c, d', c, d
combine 'd, e', d, e
puts "\n\nBenchmarking:"
Benchmark.benchmark(CAPTION, 8, FORMAT) do |bm|
bm.report 'threaded' do
threads = []
1.upto 1_000 do |i|
threads << Thread.new{ i + 1 }
end
threads.map &:join
end
bm.report 'deferred' do
deferred = []
1.upto 1_000 do |i|
deferred << DeferredProxy.new{ i + 1 }
end
deferred.map &:to_i
end
end
starting a
starting c
starting d
starting e
starting b
d done
a done
b done
a, b: {1=>3, 2=>4}
e done
c done
c, d: {5=>7, 6=>8}
d, e: {7=>9, 8=>10}
Benchmarking:
               user     system      total        real
threaded   0.110000   0.210000   0.320000 (  0.265290)
deferred   0.350000   0.240000   0.590000 (  0.554033)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment