atomic 0.0.6-java → 0.0.7-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{atomic}
5
- s.version = "0.0.6"
5
+ s.version = "0.0.7"
6
6
  s.authors = ["Charles Oliver Nutter", "MenTaLguY"]
7
7
  s.date = Time.now.strftime('%Y-%m-%d')
8
8
  s.description = "An atomic reference implementation for JRuby and green or GIL-threaded impls"
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $: << File.expand_path('../../lib', __FILE__)
4
+
5
+ require 'optparse'
6
+ require 'thread'
7
+ require 'benchmark'
8
+
9
+ require 'atomic'
10
+
11
+ Thread.abort_on_exception = true
12
+
13
+ $conf = {
14
+ :lock => "atomic",
15
+ :num_threads => 100,
16
+ :count => 100_000,
17
+ :count_per_thread => nil,
18
+ :slow => nil,
19
+ }
20
+
21
+ OptionParser.new do |opts|
22
+ opts.on("-c", "--count NUM") do |n|
23
+ $conf[:count] = n.to_i
24
+ end
25
+ opts.on("-p", "--count-per-thread") do |n|
26
+ $conf[:count_per_thread] = n.to_i
27
+ end
28
+ opts.on("-t", "--num-threads NUM") do |n|
29
+ $conf[:num_threads] = n.to_i
30
+ end
31
+ opts.on("-s", "--slow NUM") do |n|
32
+ $conf[:slow] = n.to_i
33
+ end
34
+ opts.on("-l", "--lock atomic|mutex") do |x|
35
+ $conf[:lock] = x
36
+ end
37
+ opts.on("-h", "--help"){ puts opts; exit }
38
+ end.parse!(ARGV)
39
+
40
+ unless $conf[:count_per_thread]
41
+ $conf[:count_per_thread] = $conf[:count] / $conf[:num_threads]
42
+ end
43
+ $conf.delete(:count)
44
+
45
+ if $conf[:slow].to_i > 0
46
+ require 'digest/md5'
47
+ def slow_down
48
+ $conf[:slow].times do |i|
49
+ Digest::MD5.hexdigest(i.to_s)
50
+ end
51
+ end
52
+
53
+ ret = []
54
+ 10.times do
55
+ m = Benchmark.measure{ slow_down }
56
+ ret << m.real
57
+ end
58
+
59
+ $conf[:slow_time] = [ret.min, ret.max]
60
+ else
61
+ def slow_down; end
62
+ end
63
+
64
+ $stderr.puts $conf.inspect
65
+
66
+ def para_prepare(&block)
67
+ num_threads = $conf[:num_threads]
68
+ count = $conf[:count_per_thread]
69
+
70
+ if num_threads % 2 > 0
71
+ raise ArgumentError, "num_threads must be a multiple of two"
72
+ end
73
+
74
+ # Keep those threads together
75
+ tg = ThreadGroup.new
76
+
77
+ num_threads.times do |i|
78
+ diff = (i % 2 == 0) ? 1 : -1
79
+
80
+ t = Thread.new do
81
+ nil until $go
82
+ count.times do
83
+ yield diff
84
+ end
85
+ end
86
+
87
+ tg.add(t)
88
+ end
89
+
90
+ # Make sure all threads are started
91
+ while tg.list.find{|t| t.status != "run"}
92
+ Thread.pass
93
+ end
94
+
95
+ # For good measure
96
+ GC.start
97
+
98
+ $go = false
99
+
100
+ tg
101
+ end
102
+
103
+
104
+
105
+ $tg = nil
106
+ if $conf[:lock] == "atomic"
107
+ $atom = Atomic.new(0)
108
+ $tg = para_prepare do |diff|
109
+ $atom.update do |x|
110
+ slow_down
111
+ x + diff
112
+ end
113
+ end
114
+ else
115
+ $lock = Mutex.new
116
+ $value = 0
117
+ $tg = para_prepare do |diff|
118
+ $lock.synchronize do
119
+ slow_down
120
+ $value += diff
121
+ end
122
+ end
123
+ end
124
+
125
+
126
+ # Run !
127
+ #
128
+ # NOTE: It seems to me that this measurement method
129
+ # is sensible to how the system dispatches his resources.
130
+ #
131
+ # More precise caluclation could be done using
132
+ # getrusage's times
133
+ ret = Benchmark.measure do
134
+ $go = true
135
+ $tg.list.each{|t| t.join}
136
+ $go = false
137
+ end
138
+ puts ret.real
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env ruby
2
+ require 'optparse'
3
+
4
+ conf = {
5
+ :vary => "threads",
6
+ :lock => "atomic"
7
+ }
8
+
9
+ OptionParser.new do |opts|
10
+ opts.on("-l", "--lock atomic|mutex") do |l|
11
+ conf[:lock] = l
12
+ end
13
+ opts.on("-v", "--vary threads|speed") do |v|
14
+ conf[:vary] = v
15
+ end
16
+ opts.on("-h", "--help"){ puts opts; exit }
17
+ end.parse!(ARGV)
18
+
19
+ result = File.open("results_#{conf[:lock]}_#{conf[:vary]}.csv", "w")
20
+
21
+
22
+ if conf[:vary] == "threads"
23
+ # Vary the number of concurrent threads that update the value.
24
+ #
25
+ # There is a total count of 1mio updates that is distributed
26
+ # between the number of threads.
27
+ #
28
+ # A pair number of threads is used so that even add and odd substract 1.
29
+ # This avoid creating instances for Bignum since the number should
30
+ # stay in the Fixnum range.
31
+ #
32
+ (1..100).each do |i|
33
+ i = i * 2
34
+
35
+ ret = []
36
+ 10.times do
37
+ ret << `ruby ./bench_atomic_1.rb -l #{conf[:lock]} -t #{i}`.to_f
38
+ end
39
+
40
+ line = ([i] + ret).join(', ')
41
+
42
+ puts line
43
+ result.puts line
44
+ end
45
+ elsif conf[:vary] == "speed"
46
+ # Varies the execution time of the update block
47
+ # by using long calulation (MD5)
48
+ #
49
+ # NOTE: Thread.pass and sleep() are not usable by the atomic
50
+ # lock. It needs to run the whole block without hitting
51
+ # another atomic update otherwise it has to retry
52
+ #
53
+ # The expected result is that the atomic lock's performance
54
+ # will hit a certain threshold where it will be worse than mutexes.
55
+ #
56
+ (1..30).each do |i|
57
+
58
+ ret = []
59
+ 10.times do
60
+ ret << `ruby ./bench_atomic_1.rb -l #{conf[:lock]} -s #{i}`.to_f
61
+ end
62
+
63
+ line = ([i] + ret).join(', ')
64
+
65
+ puts line
66
+ result.puts line
67
+ end
68
+ end
Binary file
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: atomic
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.6
5
+ version: 0.0.7
6
6
  platform: java
7
7
  authors:
8
8
  - Charles Oliver Nutter
@@ -11,7 +11,7 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2011-09-06 00:00:00 Z
14
+ date: 2011-11-28 00:00:00 Z
15
15
  dependencies: []
16
16
 
17
17
  description: An atomic reference implementation for JRuby and green or GIL-threaded impls
@@ -29,8 +29,9 @@ files:
29
29
  - lib/atomic_reference.jar
30
30
  - examples/atomic_example.rb
31
31
  - examples/bench_atomic.rb
32
+ - examples/bench_atomic_1.rb
33
+ - examples/graph_atomic_bench.rb
32
34
  - test/test_atomic.rb
33
- - README.txt
34
35
  - atomic.gemspec
35
36
  - Rakefile
36
37
  homepage: http://github.com/headius/ruby-atomic
data/README.txt DELETED
@@ -1,33 +0,0 @@
1
- atomic: An atomic reference implementation for JRuby and green or GIL-threaded
2
- Ruby implementations (MRI 1.8/1.9, Rubinius)
3
-
4
- == Summary ==
5
-
6
- This library provides:
7
-
8
- * an Atomic class that guarantees atomic updates to its contained value
9
-
10
- The Atomic class provides accessors for the contained "value" plus two update
11
- methods:
12
-
13
- * update will run the provided block, passing the current value and replacing
14
- it with the block result iff the value has not been changed in the mean time.
15
- It may run the block repeatedly if there are other concurrent updates in
16
- progress.
17
- * try_update will run the provided block, passing the current value and
18
- replacing it with the block result. If the value changes before the update
19
- can happen, it will throw Atomic::ConcurrentUpdateError.
20
-
21
- The atomic repository is at http://github.com/headius/ruby-atomic.
22
-
23
- == Usage ==
24
-
25
- require 'atomic'
26
-
27
- my_atomic = Atomic.new(0)
28
- my_atomic.update {|v| v + 1}
29
- begin
30
- my_atomic.try_update {|v| v + 1}
31
- rescue Atomic::ConcurrentUpdateError => cue
32
- # deal with it (retry, propagate, etc)
33
- end