agent 0.1.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/.rspec +0 -0
- data/Gemfile +0 -1
- data/Gemfile.lock +12 -12
- data/README.md +51 -36
- data/Rakefile +5 -0
- data/agent.gemspec +1 -0
- data/autotest/discover.rb +9 -1
- data/benchmark/multi_ruby_bench.sh +87 -0
- data/benchmark/sieve.rb +238 -0
- data/examples/agent-workers.rb +51 -0
- data/examples/producer-consumer.rb +15 -0
- data/lib/agent.rb +1 -15
- data/lib/agent/all.rb +22 -0
- data/lib/agent/blocking_once.rb +26 -0
- data/lib/agent/channel.rb +88 -41
- data/lib/agent/error.rb +15 -0
- data/lib/agent/errors.rb +14 -0
- data/lib/agent/go.rb +9 -0
- data/lib/agent/kernel/channel.rb +7 -0
- data/lib/agent/kernel/go.rb +7 -0
- data/lib/agent/kernel/select.rb +7 -0
- data/lib/agent/notifier.rb +34 -0
- data/lib/agent/once.rb +32 -0
- data/lib/agent/pop.rb +70 -0
- data/lib/agent/push.rb +70 -0
- data/lib/agent/queue.rb +133 -0
- data/lib/agent/queue/buffered.rb +68 -0
- data/lib/agent/queue/unbuffered.rb +88 -0
- data/lib/agent/queues.rb +50 -0
- data/lib/agent/selector.rb +119 -0
- data/lib/agent/uuid.rb +36 -0
- data/lib/agent/version.rb +1 -1
- data/lib/agent/wait_group.rb +43 -0
- data/spec/blocking_once_spec.rb +122 -0
- data/spec/channel_spec.rb +153 -82
- data/spec/error_spec.rb +15 -0
- data/spec/examples/channel_of_channels_spec.rb +17 -14
- data/spec/examples/producer_consumer_spec.rb +26 -16
- data/spec/examples/sieve_spec.rb +43 -37
- data/spec/go_spec.rb +17 -0
- data/spec/notifier_spec.rb +42 -0
- data/spec/once_spec.rb +91 -0
- data/spec/pop_spec.rb +97 -0
- data/spec/push_spec.rb +95 -0
- data/spec/queue_spec.rb +335 -37
- data/spec/queues_spec.rb +28 -0
- data/spec/selector_spec.rb +398 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/uuid_spec.rb +13 -0
- data/spec/wait_group_spec.rb +45 -0
- metadata +94 -54
- data/lib/agent/transport/queue.rb +0 -82
- data/spec/helper.rb +0 -5
data/.rspec
ADDED
File without changes
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,22 +1,21 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
agent (0.0
|
4
|
+
agent (1.0.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: http://rubygems.org/
|
8
8
|
specs:
|
9
|
-
diff-lcs (1.1.
|
10
|
-
|
11
|
-
|
12
|
-
rspec-
|
13
|
-
rspec-
|
14
|
-
|
15
|
-
rspec-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
rspec-expectations (~> 2.0.1)
|
9
|
+
diff-lcs (1.1.3)
|
10
|
+
rake (0.9.2.2)
|
11
|
+
rspec (2.9.0)
|
12
|
+
rspec-core (~> 2.9.0)
|
13
|
+
rspec-expectations (~> 2.9.0)
|
14
|
+
rspec-mocks (~> 2.9.0)
|
15
|
+
rspec-core (2.9.0)
|
16
|
+
rspec-expectations (2.9.0)
|
17
|
+
diff-lcs (~> 1.1.3)
|
18
|
+
rspec-mocks (2.9.0)
|
20
19
|
|
21
20
|
PLATFORMS
|
22
21
|
java
|
@@ -24,4 +23,5 @@ PLATFORMS
|
|
24
23
|
|
25
24
|
DEPENDENCIES
|
26
25
|
agent!
|
26
|
+
rake
|
27
27
|
rspec
|
data/README.md
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
# Agent
|
2
2
|
|
3
|
-
Agent is
|
3
|
+
Agent is an attempt at [Go-like (CSP / pi-calculus) concurrency in Ruby](http://www.igvita.com/2010/12/02/concurrency-with-actors-goroutines-ruby/), but with an additional twist. It is a collection of different [process calculi](http://en.wikipedia.org/wiki/Process_calculus) primitives and patterns, with no specific, idiomatic affiliation to any specific implementation. A few available patterns so far:
|
4
4
|
|
5
5
|
- Goroutines on top of green Ruby threads
|
6
|
-
- Named, in-memory channels
|
6
|
+
- Named, Typed, Bufferd and Unbufferred in-memory "channels"
|
7
|
+
- Selectable "channels"
|
7
8
|
|
8
|
-
This gem is a work in progress
|
9
|
+
This gem is a work in progress, so treat it as such.
|
9
10
|
|
10
11
|
# Working Code Examples
|
11
12
|
|
@@ -14,29 +15,63 @@ This gem is a work in progress & an experiment, so treat it as such. At the mome
|
|
14
15
|
* [Sieve of Eratosthenes](https://github.com/igrigorik/agent/blob/master/spec/examples/sieve_spec.rb)
|
15
16
|
|
16
17
|
# Example: Goroutine Generator
|
18
|
+
A simple multi-threaded consumer-producer, except without a thread or a mutex in sight! Note that by default Agent channels are unbuffered, meaning that the size is implicitly set to 0. Hence, in example below, the producer will generate a single value, and block until we call receive - rinse, repeat.
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
+
```ruby
|
21
|
+
c = channel!(Integer)
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
-
|
23
|
+
go! do
|
24
|
+
i = 0
|
25
|
+
loop { c << (i += 1) }
|
26
|
+
end
|
24
27
|
|
25
|
-
|
28
|
+
p c.receive.first # => 1
|
29
|
+
p c.receive.first # => 2
|
30
|
+
```
|
26
31
|
|
27
|
-
|
28
|
-
|
32
|
+
# Example: Multi-channel selector
|
33
|
+
A "select" statement chooses which of a set of possible communications will proceed. It looks similar to a "switch" statement but with the cases all referring to communication operations. Select will block until one of the channels becomes available:
|
29
34
|
|
30
|
-
|
35
|
+
```ruby
|
36
|
+
cw = channel!(Integer, 1)
|
37
|
+
cr = channel!(Integer, 1)
|
31
38
|
|
32
|
-
|
33
|
-
|
39
|
+
select do |s|
|
40
|
+
s.case(cr, :receive) { |value| do_something(value) }
|
41
|
+
s.case(cw, :send, 3)
|
42
|
+
end
|
43
|
+
```
|
34
44
|
|
45
|
+
In example above, cr is currently unavailable to read from (since its empty), but cw is ready for writing since the channel is buffered and empty. Hence, select will immediately choose the cw case and execute that code block.
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
cr = channel!(Integer, 1)
|
49
|
+
|
50
|
+
select do |s|
|
51
|
+
s.case(cr, :receive) { |value| do_something(value) }
|
52
|
+
s.default { puts :default }
|
53
|
+
end
|
54
|
+
```
|
55
|
+
|
56
|
+
In this example, cr is unavailable for read (since its empty), but we also provide "default" case which is executed immediately if no other cases are matched. In other words, no blocking.
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
cr = channel!(Integer, 1)
|
60
|
+
|
61
|
+
select do |s|
|
62
|
+
s.case(cr, :receive) { |value| do_something(value) }
|
63
|
+
s.timeout(1.0) { puts :timeout }
|
64
|
+
end
|
65
|
+
```
|
66
|
+
|
67
|
+
Once again, cr is empty, hence cannot be read from and there is no default block. Select will block until cr is readable or until the timeout condition is met - which in the case above is set to 1 second.
|
35
68
|
|
36
69
|
# Go & π-calculus: Background & Motivation
|
37
70
|
|
38
71
|
*Do not communicate by sharing memory; instead, share memory by communicating.*
|
39
72
|
|
73
|
+
See [Concurrency with Actors, Goroutines & Ruby](http://www.igvita.com/2010/12/02/concurrency-with-actors-goroutines-ruby/) for motivation and comparison to other concurrency models.
|
74
|
+
|
40
75
|
Concurrent programming in many environments is made difficult by the subtleties required to implement correct access to shared variables. Google's Go encourages a different approach in which shared values are passed around on channels and, in fact, never actively shared by separate threads of execution. Only one goroutine has access to the value at any given time. Data races cannot occur, by design.
|
41
76
|
|
42
77
|
One way to think about this model is to consider a typical single-threaded program running on one CPU. It has no need for synchronization primitives. Now run another such instance; it too needs no synchronization. Now let those two communicate; if the communication is the synchronizer, there's still no need for other synchronization. Unix pipelines, for example, fit this model perfectly. Although Go's approach to concurrency originates in Hoare's Communicating Sequential Processes (CSP), it can also be seen as a type-safe generalization of Unix pipes.
|
@@ -46,28 +81,8 @@ To learn more about Go see following resources:
|
|
46
81
|
* [golang.org](http://golang.org/)
|
47
82
|
* [Go's concurrency](http://golang.org/doc/effective_go.html#concurrency)
|
48
83
|
* [Go's channels](http://golang.org/doc/effective_go.html#channels)
|
84
|
+
* [Go's select statement](http://golang.org/doc/go_spec.html#Select_statements)
|
49
85
|
|
50
86
|
# License
|
51
87
|
|
52
|
-
|
53
|
-
|
54
|
-
Copyright (c) 2010 Ilya Grigorik
|
55
|
-
|
56
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
57
|
-
a copy of this software and associated documentation files (the
|
58
|
-
'Software'), to deal in the Software without restriction, including
|
59
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
60
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
61
|
-
permit persons to whom the Software is furnished to do so, subject to
|
62
|
-
the following conditions:
|
63
|
-
|
64
|
-
The above copyright notice and this permission notice shall be
|
65
|
-
included in all copies or substantial portions of the Software.
|
66
|
-
|
67
|
-
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
68
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
69
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
70
|
-
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
71
|
-
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
72
|
-
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
73
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
88
|
+
The MIT License - Copyright (c) 2011 Ilya Grigorik
|
data/Rakefile
CHANGED
data/agent.gemspec
CHANGED
data/autotest/discover.rb
CHANGED
@@ -0,0 +1,87 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
if [[ -s "$HOME/.rvm/scripts/rvm" ]] ; then
|
4
|
+
|
5
|
+
# First try to load from a user install
|
6
|
+
source "$HOME/.rvm/scripts/rvm"
|
7
|
+
|
8
|
+
elif [[ -s "/usr/local/rvm/scripts/rvm" ]] ; then
|
9
|
+
|
10
|
+
# Then try to load from a root install
|
11
|
+
source "/usr/local/rvm/scripts/rvm"
|
12
|
+
|
13
|
+
else
|
14
|
+
|
15
|
+
printf "ERROR: An RVM installation was not found.\n"
|
16
|
+
|
17
|
+
fi
|
18
|
+
|
19
|
+
echo
|
20
|
+
echo `ruby -v`
|
21
|
+
echo
|
22
|
+
ruby benchmark/sieve.rb 0
|
23
|
+
ruby benchmark/sieve.rb 1
|
24
|
+
ruby benchmark/sieve.rb 2
|
25
|
+
ruby benchmark/sieve.rb 3
|
26
|
+
echo
|
27
|
+
rvm use 1.8.7
|
28
|
+
echo
|
29
|
+
echo `ruby -v`
|
30
|
+
echo
|
31
|
+
ruby benchmark/sieve.rb 0
|
32
|
+
ruby benchmark/sieve.rb 1
|
33
|
+
ruby benchmark/sieve.rb 2
|
34
|
+
ruby benchmark/sieve.rb 3
|
35
|
+
echo
|
36
|
+
rvm use 1.9.2
|
37
|
+
echo
|
38
|
+
echo `ruby -v`
|
39
|
+
echo
|
40
|
+
ruby benchmark/sieve.rb 0
|
41
|
+
ruby benchmark/sieve.rb 1
|
42
|
+
ruby benchmark/sieve.rb 2
|
43
|
+
ruby benchmark/sieve.rb 3
|
44
|
+
echo
|
45
|
+
rvm use 1.9.3
|
46
|
+
echo
|
47
|
+
echo `ruby -v`
|
48
|
+
echo
|
49
|
+
ruby benchmark/sieve.rb 0
|
50
|
+
ruby benchmark/sieve.rb 1
|
51
|
+
ruby benchmark/sieve.rb 2
|
52
|
+
ruby benchmark/sieve.rb 3
|
53
|
+
echo
|
54
|
+
rvm use jruby
|
55
|
+
echo
|
56
|
+
echo `ruby -v`
|
57
|
+
echo
|
58
|
+
ruby benchmark/sieve.rb 0
|
59
|
+
ruby benchmark/sieve.rb 1
|
60
|
+
ruby benchmark/sieve.rb 2
|
61
|
+
ruby benchmark/sieve.rb 3
|
62
|
+
echo
|
63
|
+
JRUBY_OPTS="--1.9"
|
64
|
+
echo `ruby -v`
|
65
|
+
echo
|
66
|
+
ruby benchmark/sieve.rb 0
|
67
|
+
ruby benchmark/sieve.rb 1
|
68
|
+
ruby benchmark/sieve.rb 2
|
69
|
+
ruby benchmark/sieve.rb 3
|
70
|
+
echo
|
71
|
+
rvm use rbx-1.2.4
|
72
|
+
echo
|
73
|
+
echo `ruby -v`
|
74
|
+
echo
|
75
|
+
ruby benchmark/sieve.rb 0
|
76
|
+
ruby benchmark/sieve.rb 1
|
77
|
+
ruby benchmark/sieve.rb 2
|
78
|
+
ruby benchmark/sieve.rb 3
|
79
|
+
echo
|
80
|
+
rvm use rbx-2.0.testing
|
81
|
+
echo
|
82
|
+
echo `ruby -v`
|
83
|
+
echo
|
84
|
+
ruby benchmark/sieve.rb 0
|
85
|
+
ruby benchmark/sieve.rb 1
|
86
|
+
ruby benchmark/sieve.rb 2
|
87
|
+
ruby benchmark/sieve.rb 3
|
data/benchmark/sieve.rb
ADDED
@@ -0,0 +1,238 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
project_lib_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
|
3
|
+
$LOAD_PATH.unshift(project_lib_path)
|
4
|
+
require 'agent'
|
5
|
+
|
6
|
+
$size = (ARGV.pop || 0).to_i
|
7
|
+
|
8
|
+
def generate(channels)
|
9
|
+
ch = channel!(Integer, $size)
|
10
|
+
channels << ch
|
11
|
+
go!{ i = 1; loop { ch << i+= 1} }
|
12
|
+
|
13
|
+
return ch
|
14
|
+
end
|
15
|
+
|
16
|
+
def filter(in_channel, prime, channels)
|
17
|
+
out = channel!(Integer, $size)
|
18
|
+
channels << out
|
19
|
+
|
20
|
+
go! do
|
21
|
+
loop do
|
22
|
+
i, _ = in_channel.receive
|
23
|
+
out << i if (i % prime) != 0
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
return out
|
28
|
+
end
|
29
|
+
|
30
|
+
def sieve(channels)
|
31
|
+
out = channel!(Integer, $size)
|
32
|
+
channels << out
|
33
|
+
|
34
|
+
go! do
|
35
|
+
ch = generate(channels)
|
36
|
+
loop do
|
37
|
+
prime, _ = ch.receive
|
38
|
+
out << prime
|
39
|
+
ch = filter(ch, prime, channels)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
return out
|
44
|
+
end
|
45
|
+
|
46
|
+
################
|
47
|
+
################
|
48
|
+
|
49
|
+
nth_prime = 150
|
50
|
+
concurrency = 5
|
51
|
+
channels = []
|
52
|
+
|
53
|
+
puts "#{nth_prime}'s prime, #{concurrency} goroutines, channel buffer size is #{$size}"
|
54
|
+
|
55
|
+
Benchmark.bm(7) do |x|
|
56
|
+
x.report("receive") do
|
57
|
+
runners = []
|
58
|
+
|
59
|
+
concurrency.times do |n|
|
60
|
+
runners << go! do
|
61
|
+
primes = sieve(channels)
|
62
|
+
nth_prime.times { primes.receive }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
runners.map {|t| t.join}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
puts
|
71
|
+
|
72
|
+
channels.each(&:close)
|
73
|
+
|
74
|
+
__END__
|
75
|
+
|
76
|
+
The setup:
|
77
|
+
13" Macbook Air
|
78
|
+
OSX Lion 10.7.3
|
79
|
+
1.8 GHz Intel Core i7
|
80
|
+
4 GB 1333 MHz DDR3
|
81
|
+
SSD
|
82
|
+
Terminal w/ OSX Lion's system ruby by default
|
83
|
+
|
84
|
+
The command:
|
85
|
+
benchmark/multi_ruby_bench.sh
|
86
|
+
|
87
|
+
The results:
|
88
|
+
|
89
|
+
ruby 1.8.7 (2010-01-10 patchlevel 249) [universal-darwin11.0]
|
90
|
+
|
91
|
+
150's prime, 5 goroutines, channel buffer size is 0
|
92
|
+
user system total real
|
93
|
+
receive 27.100000 0.290000 27.390000 ( 27.324909)
|
94
|
+
|
95
|
+
150's prime, 5 goroutines, channel buffer size is 1
|
96
|
+
user system total real
|
97
|
+
receive 24.690000 0.280000 24.970000 ( 24.910035)
|
98
|
+
|
99
|
+
150's prime, 5 goroutines, channel buffer size is 2
|
100
|
+
user system total real
|
101
|
+
receive 24.730000 0.280000 25.010000 ( 24.946830)
|
102
|
+
|
103
|
+
150's prime, 5 goroutines, channel buffer size is 3
|
104
|
+
user system total real
|
105
|
+
receive 25.010000 0.290000 25.300000 ( 25.238002)
|
106
|
+
|
107
|
+
|
108
|
+
ruby 1.8.7 (2012-02-08 patchlevel 358) [i686-darwin11.3.0]
|
109
|
+
|
110
|
+
150's prime, 5 goroutines, channel buffer size is 0
|
111
|
+
user system total real
|
112
|
+
receive 17.890000 0.090000 17.980000 ( 17.984755)
|
113
|
+
|
114
|
+
150's prime, 5 goroutines, channel buffer size is 1
|
115
|
+
user system total real
|
116
|
+
receive 17.030000 0.090000 17.120000 ( 17.131916)
|
117
|
+
|
118
|
+
150's prime, 5 goroutines, channel buffer size is 2
|
119
|
+
user system total real
|
120
|
+
receive 17.060000 0.090000 17.150000 ( 17.168336)
|
121
|
+
|
122
|
+
150's prime, 5 goroutines, channel buffer size is 3
|
123
|
+
user system total real
|
124
|
+
receive 17.090000 0.100000 17.190000 ( 17.187443)
|
125
|
+
|
126
|
+
|
127
|
+
ruby 1.9.2p318 (2012-02-14 revision 34678) [x86_64-darwin11.3.0]
|
128
|
+
|
129
|
+
150's prime, 5 goroutines, channel buffer size is 0
|
130
|
+
user system total real
|
131
|
+
receive 5.410000 2.360000 7.770000 ( 7.241433)
|
132
|
+
|
133
|
+
150's prime, 5 goroutines, channel buffer size is 1
|
134
|
+
user system total real
|
135
|
+
receive 5.270000 1.980000 7.250000 ( 6.817536)
|
136
|
+
|
137
|
+
150's prime, 5 goroutines, channel buffer size is 2
|
138
|
+
user system total real
|
139
|
+
receive 5.330000 2.030000 7.360000 ( 6.918912)
|
140
|
+
|
141
|
+
150's prime, 5 goroutines, channel buffer size is 3
|
142
|
+
user system total real
|
143
|
+
receive 5.340000 1.950000 7.290000 ( 6.864300)
|
144
|
+
|
145
|
+
|
146
|
+
ruby 1.9.3p125 (2012-02-16 revision 34643) [x86_64-darwin11.3.0]
|
147
|
+
|
148
|
+
150's prime, 5 goroutines, channel buffer size is 0
|
149
|
+
user system total real
|
150
|
+
receive 6.470000 5.220000 11.690000 ( 8.803085)
|
151
|
+
|
152
|
+
150's prime, 5 goroutines, channel buffer size is 1
|
153
|
+
user system total real
|
154
|
+
receive 6.390000 4.190000 10.580000 ( 8.248593)
|
155
|
+
|
156
|
+
150's prime, 5 goroutines, channel buffer size is 2
|
157
|
+
user system total real
|
158
|
+
receive 6.240000 3.760000 10.000000 ( 7.936199)
|
159
|
+
|
160
|
+
150's prime, 5 goroutines, channel buffer size is 3
|
161
|
+
user system total real
|
162
|
+
receive 6.000000 3.200000 9.200000 ( 7.461371)
|
163
|
+
|
164
|
+
|
165
|
+
jruby 1.6.7 (ruby-1.8.7-p357) (2012-02-22 3e82bc8) (Java HotSpot(TM) 64-Bit Server VM 1.6.0_29) [darwin-x86_64-java]
|
166
|
+
|
167
|
+
150's prime, 5 goroutines, channel buffer size is 0
|
168
|
+
user system total real
|
169
|
+
receive 9.672000 0.000000 9.672000 ( 9.637000)
|
170
|
+
|
171
|
+
150's prime, 5 goroutines, channel buffer size is 1
|
172
|
+
user system total real
|
173
|
+
receive 12.528000 0.000000 12.528000 ( 12.494000)
|
174
|
+
|
175
|
+
150's prime, 5 goroutines, channel buffer size is 2
|
176
|
+
user system total real
|
177
|
+
receive 13.191000 0.000000 13.191000 ( 13.150000)
|
178
|
+
|
179
|
+
150's prime, 5 goroutines, channel buffer size is 3
|
180
|
+
user system total real
|
181
|
+
receive 14.702000 0.000000 14.702000 ( 14.668000)
|
182
|
+
|
183
|
+
|
184
|
+
jruby 1.6.7 (ruby-1.8.7-p357) (2012-02-22 3e82bc8) (Java HotSpot(TM) 64-Bit Server VM 1.6.0_29) [darwin-x86_64-java]
|
185
|
+
|
186
|
+
150's prime, 5 goroutines, channel buffer size is 0
|
187
|
+
user system total real
|
188
|
+
receive 9.869000 0.000000 9.869000 ( 9.836000)
|
189
|
+
|
190
|
+
150's prime, 5 goroutines, channel buffer size is 1
|
191
|
+
user system total real
|
192
|
+
receive 12.399000 0.000000 12.399000 ( 12.362000)
|
193
|
+
|
194
|
+
150's prime, 5 goroutines, channel buffer size is 2
|
195
|
+
user system total real
|
196
|
+
receive 13.146000 0.000000 13.146000 ( 13.154000)
|
197
|
+
|
198
|
+
150's prime, 5 goroutines, channel buffer size is 3
|
199
|
+
user system total real
|
200
|
+
receive 13.888000 0.000000 13.888000 ( 13.847000)
|
201
|
+
|
202
|
+
|
203
|
+
rubinius 1.2.4 (1.8.7 release 2011-07-05 JI) [x86_64-apple-darwin11.3.0]
|
204
|
+
|
205
|
+
150's prime, 5 goroutines, channel buffer size is 0
|
206
|
+
user system total real
|
207
|
+
receive 20.890472 3.099183 23.989655 ( 19.765032)
|
208
|
+
|
209
|
+
150's prime, 5 goroutines, channel buffer size is 1
|
210
|
+
user system total real
|
211
|
+
receive 21.727269 3.028753 24.756022 ( 20.554911)
|
212
|
+
|
213
|
+
150's prime, 5 goroutines, channel buffer size is 2
|
214
|
+
user system total real
|
215
|
+
receive 45.912357 5.814811 51.727168 ( 44.636344)
|
216
|
+
|
217
|
+
150's prime, 5 goroutines, channel buffer size is 3
|
218
|
+
user system total real
|
219
|
+
receive 46.211119 7.487593 53.698712 ( 44.716384)
|
220
|
+
|
221
|
+
|
222
|
+
rubinius 2.0.0dev (1.8.7 65c6146e yyyy-mm-dd JI) [x86_64-apple-darwin11.3.0]
|
223
|
+
|
224
|
+
150's prime, 5 goroutines, channel buffer size is 0
|
225
|
+
user system total real
|
226
|
+
receive 62.980970 4.578037 67.559007 ( 18.560938)
|
227
|
+
|
228
|
+
150's prime, 5 goroutines, channel buffer size is 1
|
229
|
+
user system total real
|
230
|
+
receive 52.822284 4.667321 57.489605 ( 15.986046)
|
231
|
+
|
232
|
+
150's prime, 5 goroutines, channel buffer size is 2
|
233
|
+
user system total real
|
234
|
+
receive 54.217875 4.579821 58.797696 ( 16.267339)
|
235
|
+
|
236
|
+
150's prime, 5 goroutines, channel buffer size is 3
|
237
|
+
user system total real
|
238
|
+
receive 59.092219 4.881411 63.973630 ( 17.664269)
|