require "benchmark/ips" require "bcrypt" module Enumerable def first_to_finish threads = collect { |args| Thread.new { yield(args) } } loop until done = threads.detect { |t| !t.alive? } threads.each(&:kill) done.value end def first_to_finish_with_queue queue = Queue.new threads = collect { |args| Thread.new { queue << yield(args) } } result = queue.pop threads.each(&:kill) result end def get_first_result_async result = nil threads = map do |args| Thread.new do if current_result = yield(args) result = current_result (threads - [Thread.current]).each(&:kill) # kill siblings end end end threads.each(&:join) result end end COSTS = (10..15).to_a.reverse def sferik COSTS.first_to_finish { |cost| BCrypt::Password.create("secret", :cost => cost) } end def choonkeat COSTS.first_to_finish_with_queue { |cost| BCrypt::Password.create("secret", :cost => cost) } end def juanito COSTS.get_first_result_async { |cost| BCrypt::Password.create("secret", :cost => cost) } end Benchmark.ips do |x| x.report("@sferik") { sferik } x.report("@choonkeat") { choonkeat } x.report("@JuanitoFatas") { juanito } x.compare! end