parallel 0.6.5 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data.tar.gz.sig +0 -0
- data/Gemfile.lock +1 -1
- data/Readme.md +1 -1
- data/lib/parallel.rb +49 -34
- data/lib/parallel/version.rb +1 -1
- data/spec/cases/parallel_fast_exit.rb +7 -0
- data/spec/cases/parallel_start_and_kill.rb +8 -2
- data/spec/parallel_spec.rb +37 -11
- metadata +5 -4
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/Gemfile.lock
CHANGED
data/Readme.md
CHANGED
@@ -78,7 +78,7 @@ gem install ruby-progressbar
|
|
78
78
|
```Ruby
|
79
79
|
require 'ruby-progressbar'
|
80
80
|
progress = ProgressBar.create(:title => "The Progress", :total => 100)
|
81
|
-
Parallel.map(1..100, :finish => lambda { |
|
81
|
+
Parallel.map(1..100, :finish => lambda { |item, i| progress.increment }) { sleep 1 }
|
82
82
|
```
|
83
83
|
|
84
84
|
Tips
|
data/lib/parallel.rb
CHANGED
@@ -66,7 +66,7 @@ module Parallel
|
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
-
wait_for_threads(threads)
|
69
|
+
kill_on_ctrl_c(threads) { wait_for_threads(threads) }
|
70
70
|
|
71
71
|
out
|
72
72
|
end
|
@@ -196,29 +196,30 @@ module Parallel
|
|
196
196
|
current_index = -1
|
197
197
|
results = []
|
198
198
|
exception = nil
|
199
|
+
kill_on_ctrl_c(workers.map(&:pid)) do
|
200
|
+
in_threads(options[:count]) do |i|
|
201
|
+
worker = workers[i]
|
199
202
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
else
|
216
|
-
results[index] = output
|
203
|
+
begin
|
204
|
+
loop do
|
205
|
+
break if exception
|
206
|
+
index = Thread.exclusive{ current_index += 1 }
|
207
|
+
break if index >= items.size
|
208
|
+
|
209
|
+
output = with_instrumentation items[index], index, options do
|
210
|
+
worker.work(index)
|
211
|
+
end
|
212
|
+
|
213
|
+
if ExceptionWrapper === output
|
214
|
+
exception = output.exception
|
215
|
+
else
|
216
|
+
results[index] = output
|
217
|
+
end
|
217
218
|
end
|
219
|
+
ensure
|
220
|
+
worker.close_pipes
|
221
|
+
worker.wait # if it goes zombie, rather wait here to be able to debug
|
218
222
|
end
|
219
|
-
ensure
|
220
|
-
worker.close_pipes
|
221
|
-
worker.wait # if it goes zombie, rather wait here to be able to debug
|
222
223
|
end
|
223
224
|
end
|
224
225
|
|
@@ -230,8 +231,6 @@ module Parallel
|
|
230
231
|
Array.new(options[:count]).each do
|
231
232
|
workers << worker(items, options.merge(:started_workers => workers), &block)
|
232
233
|
end
|
233
|
-
|
234
|
-
kill_on_ctrl_c(workers.map(&:pid))
|
235
234
|
workers
|
236
235
|
end
|
237
236
|
|
@@ -302,19 +301,35 @@ module Parallel
|
|
302
301
|
[count, options]
|
303
302
|
end
|
304
303
|
|
305
|
-
# kill all these
|
306
|
-
def kill_on_ctrl_c(
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
304
|
+
# kill all these pids or threads if user presses Ctrl+c
|
305
|
+
def kill_on_ctrl_c(things)
|
306
|
+
if @to_be_killed
|
307
|
+
@to_be_killed << things
|
308
|
+
else
|
309
|
+
@to_be_killed = [things]
|
310
|
+
Signal.trap :SIGINT do
|
311
|
+
if @to_be_killed.any?
|
312
|
+
$stderr.puts 'Parallel execution interrupted, exiting ...'
|
313
|
+
@to_be_killed.flatten.compact.each { |thing| kill_that_thing!(thing) }
|
315
314
|
end
|
315
|
+
exit 1 # Quit with 'failed' signal
|
316
|
+
end
|
317
|
+
end
|
318
|
+
yield
|
319
|
+
ensure
|
320
|
+
@to_be_killed.pop # free threads for GC and do not kill pids that could be used for new processes
|
321
|
+
end
|
322
|
+
|
323
|
+
def kill_that_thing!(thing)
|
324
|
+
if thing.is_a?(Thread)
|
325
|
+
thing.kill
|
326
|
+
else
|
327
|
+
begin
|
328
|
+
Process.kill(:KILL, thing)
|
329
|
+
rescue Errno::ESRCH
|
330
|
+
# some linux systems already automatically killed the children at this point
|
331
|
+
# so we just ignore them not being there
|
316
332
|
end
|
317
|
-
exit 1 # Quit with 'failed' signal
|
318
333
|
end
|
319
334
|
end
|
320
335
|
|
data/lib/parallel/version.rb
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
require File.expand_path('spec/spec_helper')
|
2
2
|
|
3
|
-
|
3
|
+
method = case ARGV[0]
|
4
|
+
when "PROCESS" then :in_processes
|
5
|
+
when "THREAD" then :in_threads
|
6
|
+
else raise "Learn to use this!"
|
7
|
+
end
|
8
|
+
|
9
|
+
Parallel.send(method, 2) do
|
4
10
|
sleep 10
|
5
11
|
puts "I should have been killed earlier..."
|
6
|
-
end
|
12
|
+
end
|
data/spec/parallel_spec.rb
CHANGED
@@ -7,6 +7,13 @@ describe Parallel do
|
|
7
7
|
Time.now.to_f - t
|
8
8
|
end
|
9
9
|
|
10
|
+
def kill_process_with_name(file)
|
11
|
+
running_processes = `ps -f`.split("\n").map{ |line| line.split(/\s+/) }
|
12
|
+
pid_index = running_processes.detect { |p| p.include?("UID") }.index("UID") + 1
|
13
|
+
parent_pid = running_processes.detect { |p| p.include?(file) and not p.include?("sh") }[pid_index]
|
14
|
+
`kill -2 #{parent_pid}`
|
15
|
+
end
|
16
|
+
|
10
17
|
describe ".processor_count" do
|
11
18
|
it "returns a number" do
|
12
19
|
(1..999).should include(Parallel.processor_count)
|
@@ -58,20 +65,39 @@ describe Parallel do
|
|
58
65
|
|
59
66
|
it "kills the processes when the main process gets killed through ctrl+c" do
|
60
67
|
time_taken{
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
parent_pid = running_processes.detect{ |p| p.include?("spec/cases/parallel_start_and_kill.rb") }[pid_index]
|
69
|
-
`kill -2 #{parent_pid}` #simulates Ctrl+c
|
70
|
-
sleep 1
|
71
|
-
}.should_not change{`ps`.split("\n").size}
|
68
|
+
lambda{
|
69
|
+
t = Thread.new { `ruby spec/cases/parallel_start_and_kill.rb PROCESS` }
|
70
|
+
sleep 1
|
71
|
+
kill_process_with_name("spec/cases/parallel_start_and_kill.rb") #simulates Ctrl+c
|
72
|
+
sleep 1
|
73
|
+
puts t.value
|
74
|
+
}.should_not change{`ps`.split("\n").size}
|
72
75
|
}.should <= 3
|
73
76
|
end
|
74
77
|
|
78
|
+
it "kills the threads when the main process gets killed through ctrl+c" do
|
79
|
+
time_taken{
|
80
|
+
lambda{
|
81
|
+
Thread.new { `ruby spec/cases/parallel_start_and_kill.rb THREAD` }
|
82
|
+
sleep 1
|
83
|
+
kill_process_with_name("spec/cases/parallel_start_and_kill.rb") #simulates Ctrl+c
|
84
|
+
sleep 1
|
85
|
+
}.should_not change{`ps`.split("\n").size}
|
86
|
+
}.should <= 3
|
87
|
+
end
|
88
|
+
|
89
|
+
it "does not kill anything on ctrl+c when everything has finished" do
|
90
|
+
time_taken do
|
91
|
+
t = Thread.new { `ruby spec/cases/parallel_fast_exit.rb 2>&1` }
|
92
|
+
sleep 2
|
93
|
+
kill_process_with_name("spec/cases/parallel_fast_exit.rb") #simulates Ctrl+c
|
94
|
+
sleep 1
|
95
|
+
result = t.value
|
96
|
+
result.scan(/I finished/).size.should == 3
|
97
|
+
result.should_not include("Parallel execution interrupted")
|
98
|
+
end.should <= 4
|
99
|
+
end
|
100
|
+
|
75
101
|
it "saves time" do
|
76
102
|
time_taken{
|
77
103
|
`ruby spec/cases/parallel_sleeping_2.rb`
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: parallel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -36,7 +36,7 @@ cert_chain:
|
|
36
36
|
VHNmKzZNYWVud0FNa0FnSGRzd0dzSnp0T25ObkJhM0YKeTBrQ1NXbUs2RCt4
|
37
37
|
L1NiZlM2cjdLZTA3TVJxemlKZEI5R3VFMSswY0lSdUZoOEVRK0xONkhYQ0tN
|
38
38
|
NXBvbi9HVQp5Y3dNWGZsMAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
|
39
|
-
date: 2013-
|
39
|
+
date: 2013-06-14 00:00:00.000000000 Z
|
40
40
|
dependencies: []
|
41
41
|
description:
|
42
42
|
email: michael@grosser.it
|
@@ -69,6 +69,7 @@ files:
|
|
69
69
|
- spec/cases/map_with_threads_and_break.rb
|
70
70
|
- spec/cases/map_with_threads_and_exceptions.rb
|
71
71
|
- spec/cases/no_dump_with_each.rb
|
72
|
+
- spec/cases/parallel_fast_exit.rb
|
72
73
|
- spec/cases/parallel_high_fork_rate.rb
|
73
74
|
- spec/cases/parallel_influence_outside_data.rb
|
74
75
|
- spec/cases/parallel_map.rb
|
@@ -100,7 +101,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
100
101
|
version: '0'
|
101
102
|
segments:
|
102
103
|
- 0
|
103
|
-
hash:
|
104
|
+
hash: 3171902731114170128
|
104
105
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
106
|
none: false
|
106
107
|
requirements:
|
@@ -109,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
109
110
|
version: '0'
|
110
111
|
segments:
|
111
112
|
- 0
|
112
|
-
hash:
|
113
|
+
hash: 3171902731114170128
|
113
114
|
requirements: []
|
114
115
|
rubyforge_project:
|
115
116
|
rubygems_version: 1.8.25
|
metadata.gz.sig
CHANGED
Binary file
|