Permalink
Browse files

Add future benchmarks from rubyconf 2015

  • Loading branch information...
1 parent e17e6d1 commit 7cb2dc6130df19e53f2157a71c90e2153d60a467 @pitr-ch pitr-ch committed Dec 8, 2015
Showing with 620 additions and 3 deletions.
  1. +4 −0 Gemfile
  2. +20 −0 benchmarks/default.config.rb
  3. +31 −0 benchmarks/futures-rubyconf2015.config.rb
  4. +3 −0 benchmarks/futures-rubyconf2015/benchmarks/cr-cas-complete.rb
  5. +3 −0 benchmarks/futures-rubyconf2015/benchmarks/cr-cas-fulfill.rb
  6. +3 −0 benchmarks/futures-rubyconf2015/benchmarks/cr-cas-new.rb
  7. +3 −0 benchmarks/futures-rubyconf2015/benchmarks/cr-cas-value.rb
  8. +3 −0 benchmarks/futures-rubyconf2015/benchmarks/cr-complete.rb
  9. +3 −0 benchmarks/futures-rubyconf2015/benchmarks/cr-fulfill.rb
  10. +3 −0 benchmarks/futures-rubyconf2015/benchmarks/cr-new.rb
  11. +3 −0 benchmarks/futures-rubyconf2015/benchmarks/cr-value.rb
  12. +3 −0 benchmarks/futures-rubyconf2015/benchmarks/mutex-complete.rb
  13. +3 −0 benchmarks/futures-rubyconf2015/benchmarks/mutex-fulfill.rb
  14. +3 −0 benchmarks/futures-rubyconf2015/benchmarks/mutex-new.rb
  15. +3 −0 benchmarks/futures-rubyconf2015/benchmarks/mutex-value.rb
  16. +18 −0 benchmarks/futures-rubyconf2015/benchmarks/special-complete.rb
  17. +18 −0 benchmarks/futures-rubyconf2015/benchmarks/special-fulfill.rb
  18. +18 −0 benchmarks/futures-rubyconf2015/benchmarks/special-new.rb
  19. +18 −0 benchmarks/futures-rubyconf2015/benchmarks/special-value.rb
  20. +23 −0 benchmarks/futures-rubyconf2015/lib/bench_complete.rb
  21. +20 −0 benchmarks/futures-rubyconf2015/lib/bench_fulfill.rb
  22. +20 −0 benchmarks/futures-rubyconf2015/lib/bench_new.rb
  23. +24 −0 benchmarks/futures-rubyconf2015/lib/bench_value.rb
  24. +2 −0 benchmarks/futures-rubyconf2015/lib/concurrent_needed.rb
  25. +83 −0 benchmarks/futures-rubyconf2015/lib/cr_cas_future.rb
  26. +49 −0 benchmarks/futures-rubyconf2015/lib/cr_future.rb
  27. +19 −0 benchmarks/futures-rubyconf2015/lib/example_reordering_ivar.rb
  28. +39 −0 benchmarks/futures-rubyconf2015/lib/example_usage_of_future.rb
  29. +36 −0 benchmarks/futures-rubyconf2015/lib/gvl_future.rb
  30. +43 −0 benchmarks/futures-rubyconf2015/lib/jruby_future.rb
  31. +37 −0 benchmarks/futures-rubyconf2015/lib/mutex_future.rb
  32. +46 −0 benchmarks/futures-rubyconf2015/lib/rbx_future.rb
  33. +9 −0 benchmarks/readme.md
  34. +2 −0 lib/concurrent/synchronization.rb
  35. +1 −1 lib/concurrent/synchronization/abstract_lockable_object.rb
  36. +4 −2 lib/concurrent/synchronization/truffle_lockable_object.rb
View
@@ -25,3 +25,7 @@ group :testing do
gem 'simplecov', '~> 0.10.0', :require => false
gem 'coveralls', '~> 0.8.2', :require => false
end
+
+group :benchmarks do
+ gem 'bench9000'
+end
@@ -0,0 +1,20 @@
+rbenv '2.2.3'
+
+rbenv 'jruby-9.0.4.0-indy',
+ 'jruby-9.0.4.0',
+ '-Xcompile.invokedynamic=true'
+
+rbenv 'rbx-2.5.8'
+
+rbenv 'jruby-dev-truffle-graal',
+ 'jruby-master+graal-dev',
+ '-J-Xmx2G -X+T'
+
+binary 'baseline', 'false'
+
+
+rubies = ['baseline', '2.2.3', 'jruby-9.0.4.0-indy', 'rbx-2.5.8']
+rubies = ['2.2.3', 'jruby-9.0.4.0-indy', 'rbx-2.5.8']
+implementation_group 'rubies', *rubies
+implementation_group 'rubies+truffle', *rubies, 'jruby-dev-truffle-graal'
+
@@ -0,0 +1,31 @@
+future_benchmarks = [
+ 'mutex-complete',
+ 'mutex-value',
+ 'mutex-fulfill',
+ 'special-complete',
+ 'special-value',
+ 'special-fulfill',
+ 'cr-complete',
+ 'cr-value',
+ 'cr-fulfill',
+ 'cr-cas-complete',
+ 'cr-cas-value',
+ 'cr-cas-fulfill',
+]
+
+future_new_benchmarks = [
+ 'cr-cas-new',
+ 'cr-new',
+ 'special-new'
+]
+
+all_bechmarks = future_benchmarks + future_new_benchmarks
+
+all_bechmarks.each do |name|
+ benchmark "future-#{name}",
+ "#{default_benchmarks_dir}/futures-rubyconf2015/benchmarks/#{name}.rb",
+ "-I #{default_benchmarks_dir}/futures-rubyconf2015/lib"
+end
+
+benchmark_group 'future', *(future_benchmarks.map { |v| "future-#{v}" })
+benchmark_group 'future-new', *(all_bechmarks.map { |v| "future-#{v}" })
@@ -0,0 +1,3 @@
+require 'cr_cas_future'
+FutureImplementation = CRCasFuture
+require 'bench_complete'
@@ -0,0 +1,3 @@
+require 'cr_cas_future'
+FutureImplementation = CRCasFuture
+require 'bench_fulfill'
@@ -0,0 +1,3 @@
+require 'cr_cas_future'
+FutureImplementation = CRCasFuture
+require 'bench_new'
@@ -0,0 +1,3 @@
+require 'cr_cas_future'
+FutureImplementation = CRCasFuture
+require 'bench_value'
@@ -0,0 +1,3 @@
+require 'cr_future'
+FutureImplementation = CRFuture
+require 'bench_complete'
@@ -0,0 +1,3 @@
+require 'cr_future'
+FutureImplementation = CRFuture
+require 'bench_fulfill'
@@ -0,0 +1,3 @@
+require 'cr_future'
+FutureImplementation = CRFuture
+require 'bench_new'
@@ -0,0 +1,3 @@
+require 'cr_future'
+FutureImplementation = CRFuture
+require 'bench_value'
@@ -0,0 +1,3 @@
+require 'mutex_future'
+FutureImplementation = MutexFuture
+require 'bench_complete'
@@ -0,0 +1,3 @@
+require 'mutex_future'
+FutureImplementation = MutexFuture
+require 'bench_fulfill'
@@ -0,0 +1,3 @@
+require 'mutex_future'
+FutureImplementation = MutexFuture
+require 'bench_new'
@@ -0,0 +1,3 @@
+require 'mutex_future'
+FutureImplementation = MutexFuture
+require 'bench_value'
@@ -0,0 +1,18 @@
+require 'concurrent_needed'
+require 'concurrent/utility/engine'
+
+FutureImplementation = case
+ when Concurrent.on_cruby?
+ require 'gvl_future'
+ GVLFuture
+ when Concurrent.on_rbx? || Concurrent.on_truffle?
+ require 'rbx_future'
+ RBXFuture
+ when Concurrent.on_jruby?
+ require 'jruby_future'
+ JRubyFuture
+ else
+ raise
+ end
+
+require 'bench_complete'
@@ -0,0 +1,18 @@
+require 'concurrent_needed'
+require 'concurrent/utility/engine'
+
+FutureImplementation = case
+ when Concurrent.on_cruby?
+ require 'gvl_future'
+ GVLFuture
+ when Concurrent.on_rbx? || Concurrent.on_truffle?
+ require 'rbx_future'
+ RBXFuture
+ when Concurrent.on_jruby?
+ require 'jruby_future'
+ JRubyFuture
+ else
+ raise
+ end
+
+require 'bench_fulfill'
@@ -0,0 +1,18 @@
+require 'concurrent_needed'
+require 'concurrent/utility/engine'
+
+FutureImplementation = case
+ when Concurrent.on_cruby?
+ require 'gvl_future'
+ GVLFuture
+ when Concurrent.on_rbx? || Concurrent.on_truffle?
+ require 'rbx_future'
+ RBXFuture
+ when Concurrent.on_jruby?
+ require 'jruby_future'
+ JRubyFuture
+ else
+ raise
+ end
+
+require 'bench_new'
@@ -0,0 +1,18 @@
+require 'concurrent_needed'
+require 'concurrent/utility/engine'
+
+FutureImplementation = case
+ when Concurrent.on_cruby?
+ require 'gvl_future'
+ GVLFuture
+ when Concurrent.on_rbx? || Concurrent.on_truffle?
+ require 'rbx_future'
+ RBXFuture
+ when Concurrent.on_jruby?
+ require 'jruby_future'
+ JRubyFuture
+ else
+ raise
+ end
+
+require 'bench_value'
@@ -0,0 +1,23 @@
+ITERATIONS = 2_500_000
+
+def harness_input
+ FutureImplementation.new
+end
+
+def harness_sample(input)
+ ITERATIONS.times do
+ input.complete?
+ end
+
+ input.fulfill true
+
+ ITERATIONS.times do
+ input.complete?
+ end
+end
+
+def harness_verify(output)
+ true
+end
+
+require 'bench9000/harness'
@@ -0,0 +1,20 @@
+ITERATIONS = 2_500_000
+
+def harness_input
+end
+
+def harness_sample(input)
+ last_future = nil
+ ITERATIONS.times do |i|
+ last_future = FutureImplementation.new
+ last_future.fulfill i
+ end
+ last_future
+end
+
+def harness_verify(output)
+ output.value == ITERATIONS - 1
+end
+
+require 'bench9000/harness'
+
@@ -0,0 +1,20 @@
+
+ITERATIONS = 2_500_000
+
+def harness_input
+end
+
+def harness_sample(input)
+ last = nil
+ ITERATIONS.times do |i|
+ last = FutureImplementation.new
+ end
+ last
+end
+
+def harness_verify(output)
+ output.is_a? FutureImplementation
+end
+
+require 'bench9000/harness'
+
@@ -0,0 +1,24 @@
+ITERATIONS = 5_000_000
+
+def harness_input
+ f = FutureImplementation.new
+ f.fulfill 1
+ f
+end
+
+def harness_sample(input)
+ sum = 0
+
+ ITERATIONS.times do
+ sum += input.value
+ end
+
+ sum
+end
+
+def harness_verify(output)
+ output == ITERATIONS
+end
+
+require 'bench9000/harness'
+
@@ -0,0 +1,2 @@
+concurrent_ruby_load_path = File.expand_path(File.join(File.dirname(__FILE__), '../../../lib'))
+$LOAD_PATH << concurrent_ruby_load_path unless $LOAD_PATH.include? concurrent_ruby_load_path
@@ -0,0 +1,83 @@
+require 'concurrent_needed'
+require 'concurrent/synchronization'
+require 'concurrent/atomics'
+
+class CRCasFuture < Concurrent::Synchronization::Object
+
+ class Node < Concurrent::Synchronization::Object
+ attr_volatile(:awake)
+
+ safe_initialization!
+
+ def initialize(thread)
+ super()
+ @Thread = thread
+ self.awake = false
+ end
+
+ def thread
+ @Thread
+ end
+ end
+
+ safe_initialization!
+ PENDING = Object.new
+
+ attr_atomic(:atomic_value)
+ attr_atomic(:head)
+
+ def initialize
+ super
+ self.head = nil
+ self.atomic_value = PENDING
+ end
+
+ def complete?(value = atomic_value)
+ value != PENDING
+ end
+
+ def value
+ value = atomic_value
+ return value if complete? value
+
+ begin
+ while true
+ head = self.head
+ node = Node.new Thread.current
+ break if compare_and_set_head head, node
+ end
+
+ until complete?(value = atomic_value)
+ # may go to sleep even if completed, but it has a record by then
+ sleep
+ end
+
+ value
+ ensure
+ node.awake = true
+ wakeup head
+ end
+ end
+
+ def fulfill(value)
+ if compare_and_set_atomic_value(PENDING, value)
+ wakeup head
+ else
+ raise 'already fulfilled'
+ end
+ self
+ end
+
+ private
+
+ def wakeup(node)
+ return unless node
+
+ while true
+ break if node.awake
+ # has to be confirmed
+ node.thread.wakeup
+ Thread.pass
+ end
+ end
+end
Oops, something went wrong.

0 comments on commit 7cb2dc6

Please sign in to comment.