Skip to content

Commit 635c748

Browse files
committed
Merge pull request #267 from ruby-concurrency/refactor/time-and-delay
Various updates and refactoring
2 parents 7881ac9 + b961f88 commit 635c748

29 files changed

+365
-432
lines changed

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@
4040
* All high-level abstractions default to the "io executor"
4141
* Fixed bug in `Actor` causing it to prematurely warm global thread pools on gem load
4242
- This also fixed a `RejectedExecutionError` bug when running with minitest/autorun via JRuby
43-
* Added `LazyReference`, a simpler and faster varition of `Delay`
44-
- Updated most internal uses of `Delay` with `LazyReference`
4543
* Moved global logger up to the `Concurrent` namespace and refactored the code
44+
* Optimized the performance of `Delay`
45+
- Fixed a bug in which no executor option on construction caused block execution on a global thread pool
4646

4747
## Current Release v0.8.0 (25 January 2015)
4848

README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ This library contains a variety of concurrency abstractions at high and low leve
8383
* [AtomicFixnum](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/AtomicFixnum.html)
8484
* [AtomicReference](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/MutexAtomic.html)
8585
* [Delay](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Delay.html)
86-
* [LazyReference](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/LazyReference.html)
8786
* [LazyRegister](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/LazyRegister.html)
8887
* [I-Structures](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/IVar.html) (IVar)
8988
* [M-Structures](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/MVar.html) (MVar)
@@ -123,7 +122,6 @@ require 'concurrent/exchanger' # Concurrent::Exchanger
123122
require 'concurrent/future' # Concurrent::Future
124123
require 'concurrent/ivar' # Concurrent::IVar
125124
require 'concurrent/lazy_register' # Concurrent::LazyRegister
126-
require 'concurrent/lazy_reference' # Concurrent::LazyReference
127125
require 'concurrent/mvar' # Concurrent::MVar
128126
require 'concurrent/promise' # Concurrent::Promise
129127
require 'concurrent/scheduled_task' # Concurrent::ScheduledTask

examples/at_exit_tester.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/usr/bin/env ruby
2+
3+
$: << File.expand_path('../../lib', __FILE__)
4+
5+
require 'concurrent'
6+
7+
# with this, a JRuby process will never exit
8+
Concurrent.disable_auto_termination_of_all_executors!
9+
10+
SIZE = 5
11+
12+
pool = Concurrent::FixedThreadPool.new(SIZE)
13+
14+
latch = Concurrent::CountDownLatch.new(SIZE)
15+
16+
print "Posting #{SIZE} tasks...\n"
17+
18+
SIZE.times do |i|
19+
pool.post do
20+
this = i
21+
sleep(1)
22+
print "Completing task #{i}\n"
23+
latch.count_down
24+
end
25+
end
26+
27+
print "Waiting for all tasks to complete...\n"
28+
latch.wait
29+
print "Done\n"

examples/atomic_example.rb

100644100755
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
#!/usr/bin/env ruby
2+
3+
$: << File.expand_path('../../lib', __FILE__)
4+
15
require 'concurrent/atomic'
26

37
my_atomic = Concurrent::Atomic.new(0)

examples/benchmark_atomic_boolean.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env ruby
22

3-
$:.push File.join(File.dirname(__FILE__), '../lib')
3+
$: << File.expand_path('../../lib', __FILE__)
44

55
require 'concurrent/atomics'
66
require 'benchmark'

examples/benchmark_atomic_fixnum.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env ruby
22

3-
$:.push File.join(File.dirname(__FILE__), '../lib')
3+
$: << File.expand_path('../../lib', __FILE__)
44

55
require 'concurrent/atomics'
66
require 'benchmark'

examples/benchmark_read_write_lock.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env ruby
22

3-
$:.push File.join(File.dirname(__FILE__), '../lib')
3+
$: << File.expand_path('../../lib', __FILE__)
44

55
require 'concurrent/atomic/read_write_lock'
66
require 'benchmark'

examples/graph_atomic_bench.rb

100644100755
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#!/usr/bin/env ruby
22

3+
$: << File.expand_path('../../lib', __FILE__)
4+
35
require 'optparse'
46

57
conf = {
@@ -35,7 +37,7 @@
3537

3638
ret = []
3739
10.times do
38-
ret << `ruby ./bench_atomic_1.rb -l #{conf[:lock]} -t #{i}`.to_f
40+
ret << `ruby #{File.dirname(__FILE__)}/bench_atomic_1.rb -l #{conf[:lock]} -t #{i}`.to_f
3941
end
4042

4143
line = ([i] + ret).join(', ')
@@ -58,7 +60,7 @@
5860

5961
ret = []
6062
10.times do
61-
ret << `ruby ./bench_atomic_1.rb -l #{conf[:lock]} -s #{i}`.to_f
63+
ret << `ruby #{File.dirname(__FILE__)}/bench_atomic_1.rb -l #{conf[:lock]} -s #{i}`.to_f
6264
end
6365

6466
line = ([i] + ret).join(', ')

examples/lazy_and_delay.rb

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,42 @@
33
$: << File.expand_path('../../lib', __FILE__)
44

55
require 'benchmark'
6-
7-
require 'concurrent/delay'
8-
require 'concurrent/lazy_reference'
6+
require 'thread'
7+
require 'concurrent'
98

109
n = 500_000
1110

11+
class LazyReference
12+
def initialize(&block)
13+
raise ArgumentError.new('no block given') unless block_given?
14+
@task = block
15+
@mutex = Mutex.new
16+
@value = nil
17+
@fulfilled = false
18+
end
19+
20+
def value
21+
@mutex.synchronize do
22+
unless @fulfilled
23+
begin
24+
@value = @task.call
25+
ensure
26+
@fulfilled = true
27+
end
28+
end
29+
end
30+
return @value
31+
end
32+
end
33+
1234
delay = Concurrent::Delay.new{ nil }
13-
lazy = Concurrent::LazyReference.new{ nil }
35+
lazy = LazyReference.new{ nil }
1436

1537
delay.value
1638
lazy.value
1739

18-
Benchmark.bm do |x|
19-
puts 'Benchmarking Delay...'
20-
x.report { n.times{ delay.value } }
21-
puts 'Benchmarking Lazy...'
22-
x.report { n.times{ lazy.value } }
40+
Benchmark.bmbm do |x|
41+
x.report('Delay#value') { n.times{ delay.value } }
42+
x.report('Delay#value!') { n.times{ delay.value! } }
43+
x.report('LazyReference#value') { n.times{ lazy.value } }
2344
end

examples/test_clock_variations.rb

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#!/usr/bin/env ruby
2+
3+
$: << File.expand_path('../../lib', __FILE__)
4+
5+
require 'benchmark'
6+
require 'thread'
7+
8+
class MonotonicClock
9+
def initialize
10+
@mutex = Mutex.new
11+
@last_time = Time.now.to_f
12+
end
13+
14+
def get_time_native
15+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
16+
end
17+
18+
def get_interval_native(since)
19+
Process.clock_gettime(Process::CLOCK_MONOTONIC) - since.to_f
20+
end
21+
22+
def get_time_ruby
23+
@mutex.synchronize do
24+
now = Time.now.to_f
25+
if @last_time < now
26+
@last_time = now
27+
else # clock has moved back in time
28+
@last_time += 0.000_001
29+
end
30+
end
31+
end
32+
33+
def get_interval_ruby(since)
34+
get_time_ruby - since.to_f
35+
end
36+
end
37+
38+
COUNT = 2_000_000
39+
CLOCK = MonotonicClock.new
40+
41+
native_now = CLOCK.get_time_native
42+
ruby_now = CLOCK.get_time_ruby
43+
44+
puts "Native: #{native_now}, Ruby: #{ruby_now}"
45+
46+
Benchmark.bmbm do |bm|
47+
48+
bm.report('Native time') do
49+
COUNT.times{ CLOCK.get_time_native }
50+
end
51+
52+
bm.report('Ruby time') do
53+
COUNT.times{ CLOCK.get_time_ruby }
54+
end
55+
56+
bm.report('Native interval') do
57+
COUNT.times{ CLOCK.get_interval_native(native_now) }
58+
end
59+
60+
bm.report('Ruby interval') do
61+
COUNT.times{ CLOCK.get_interval_ruby(ruby_now) }
62+
end
63+
end
64+
65+
puts "Native: #{CLOCK.get_time_native}, Ruby: #{CLOCK.get_time_ruby}"

0 commit comments

Comments
 (0)