parallel 1.21.0 → 1.22.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4dd167566b23262ceacbd640fda95c5e8d0d8149cc430f51ada53765a927cb18
4
- data.tar.gz: 6a21c00b1109d5c665a471aec4a7af7d213ded2fc9123132b6576ee65ceb1758
3
+ metadata.gz: 7efbfe49c3df93ae88464b4bd4ce85d1aaccc9c173e1a81e7cf9100fe182982c
4
+ data.tar.gz: 7e82ff83bd44c96da760d83ab665baed41bc62d53f010987951c805cf41723e4
5
5
  SHA512:
6
- metadata.gz: 1f8a810c3b7fa77e8dd2b2539238b856b9b4ea40b5df49cf2cc4af2afbd2a73d9b6f34baab614c41e7b3b8bfe1917413bfbd014f647c5b4b96e7243d5433523d
7
- data.tar.gz: 0bef1c7dc19b4738e228985512ee6cce1915f67ee29161b743821f69366d561ed8c3c5cbd4d9e6829342108fe9f10329563770d1978a660a04c58c0d9e2c8461
6
+ metadata.gz: a81cae96dd4dcfa1d287ce3e5893c830de3cb8e305236db4170db81f94de021f187da0d21462b7df5e99310002c14984fbb00aef818936c13d0ae834c1c1b2e7
7
+ data.tar.gz: 79c099a5f1f8bdad3d9f187829213d242087779605f14fb421f0172c1de1a8f853b4f13045935410a989d845d08e736e9552c8e3b9a6c3763d2dfdd27ede7daf
@@ -1,11 +1,10 @@
1
1
  # frozen_string_literal: true
2
- require 'etc'
3
-
4
2
  module Parallel
5
3
  # TODO: inline this method into parallel.rb and kill physical_processor_count in next major release
6
4
  module ProcessorCount
7
5
  # Number of processors seen by the OS, used for process scheduling
8
6
  def processor_count
7
+ require 'etc'
9
8
  @processor_count ||= Integer(ENV['PARALLEL_PROCESSOR_COUNT'] || Etc.nprocessors)
10
9
  end
11
10
 
@@ -19,7 +18,7 @@ module Parallel
19
18
  when /linux/
20
19
  cores = {} # unique physical ID / core ID combinations
21
20
  phy = 0
22
- IO.read("/proc/cpuinfo").scan(/^physical id.*|^core id.*/) do |ln|
21
+ File.read("/proc/cpuinfo").scan(/^physical id.*|^core id.*/) do |ln|
23
22
  if ln.start_with?("physical")
24
23
  phy = ln[/\d+/]
25
24
  elsif ln.start_with?("core")
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Parallel
3
- VERSION = Version = '1.21.0' # rubocop:disable Naming/ConstantName
3
+ VERSION = Version = '1.22.1' # rubocop:disable Naming/ConstantName
4
4
  end
data/lib/parallel.rb CHANGED
@@ -264,6 +264,9 @@ module Parallel
264
264
  elsif options[:in_threads]
265
265
  method = :in_threads
266
266
  size = options[method]
267
+ elsif options[:in_ractors]
268
+ method = :in_ractors
269
+ size = options[method]
267
270
  else
268
271
  method = :in_processes
269
272
  if Process.respond_to?(:fork)
@@ -285,6 +288,8 @@ module Parallel
285
288
  work_direct(job_factory, options, &block)
286
289
  elsif method == :in_threads
287
290
  work_in_threads(job_factory, options.merge(count: size), &block)
291
+ elsif method == :in_ractors
292
+ work_in_ractors(job_factory, options.merge(count: size), &block)
288
293
  else
289
294
  work_in_processes(job_factory, options.merge(count: size), &block)
290
295
  end
@@ -382,6 +387,72 @@ module Parallel
382
387
  exception || results
383
388
  end
384
389
 
390
+ def work_in_ractors(job_factory, options)
391
+ exception = nil
392
+ results = []
393
+ results_mutex = Mutex.new # arrays are not thread-safe on jRuby
394
+
395
+ callback = options[:ractor]
396
+ if block_given? || !callback
397
+ raise ArgumentError, "pass the code you want to execute as `ractor: [ClassName, :method_name]`"
398
+ end
399
+
400
+ # build
401
+ ractors = Array.new(options.fetch(:count)) do
402
+ Ractor.new do
403
+ loop do
404
+ got = receive
405
+ (klass, method_name), item, index = got
406
+ break if index == :break
407
+ begin
408
+ Ractor.yield [nil, klass.send(method_name, item), item, index]
409
+ rescue StandardError => e
410
+ Ractor.yield [e, nil, item, index]
411
+ end
412
+ end
413
+ end
414
+ end
415
+
416
+ # start
417
+ ractors.dup.each do |ractor|
418
+ if set = job_factory.next
419
+ item, index = set
420
+ instrument_start item, index, options
421
+ ractor.send [callback, item, index]
422
+ else
423
+ ractor.send([[nil, nil], nil, :break]) # stop the ractor
424
+ ractors.delete ractor
425
+ end
426
+ end
427
+
428
+ # replace with new items
429
+ while set = job_factory.next
430
+ item_next, index_next = set
431
+ done, (exception, result, item, index) = Ractor.select(*ractors)
432
+ if exception
433
+ ractors.delete done
434
+ break
435
+ end
436
+ instrument_finish item, index, result, options
437
+ results_mutex.synchronize { results[index] = (options[:preserve_results] == false ? nil : result) }
438
+
439
+ instrument_start item_next, index_next, options
440
+ done.send([callback, item_next, index_next])
441
+ end
442
+
443
+ # finish
444
+ ractors.each do |ractor|
445
+ (new_exception, result, item, index) = ractor.take
446
+ exception ||= new_exception
447
+ next if new_exception
448
+ instrument_finish item, index, result, options
449
+ results_mutex.synchronize { results[index] = (options[:preserve_results] == false ? nil : result) }
450
+ ractor.send([[nil, nil], nil, :break]) # stop the ractor
451
+ end
452
+
453
+ exception || results
454
+ end
455
+
385
456
  def work_in_processes(job_factory, options, &blk)
386
457
  workers = create_workers(job_factory, options, &blk)
387
458
  results = []
@@ -426,6 +497,7 @@ module Parallel
426
497
  end
427
498
  end
428
499
  end
500
+
429
501
  exception || results
430
502
  end
431
503
 
@@ -521,12 +593,20 @@ module Parallel
521
593
  end
522
594
 
523
595
  def with_instrumentation(item, index, options)
524
- on_start = options[:start]
525
- on_finish = options[:finish]
526
- options[:mutex].synchronize { on_start.call(item, index) } if on_start
596
+ instrument_start(item, index, options)
527
597
  result = yield
528
- options[:mutex].synchronize { on_finish.call(item, index, result) } if on_finish
598
+ instrument_finish(item, index, result, options)
529
599
  result unless options[:preserve_results] == false
530
600
  end
601
+
602
+ def instrument_finish(item, index, result, options)
603
+ return unless on_finish = options[:finish]
604
+ options[:mutex].synchronize { on_finish.call(item, index, result) }
605
+ end
606
+
607
+ def instrument_start(item, index, options)
608
+ return unless on_start = options[:start]
609
+ options[:mutex].synchronize { on_start.call(item, index) }
610
+ end
531
611
  end
532
612
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parallel
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.21.0
4
+ version: 1.22.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Grosser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-13 00:00:00.000000000 Z
11
+ date: 2022-03-25 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: michael@grosser.it
@@ -25,8 +25,8 @@ licenses:
25
25
  - MIT
26
26
  metadata:
27
27
  bug_tracker_uri: https://github.com/grosser/parallel/issues
28
- documentation_uri: https://github.com/grosser/parallel/blob/v1.21.0/Readme.md
29
- source_code_uri: https://github.com/grosser/parallel/tree/v1.21.0
28
+ documentation_uri: https://github.com/grosser/parallel/blob/v1.22.1/Readme.md
29
+ source_code_uri: https://github.com/grosser/parallel/tree/v1.22.1
30
30
  wiki_uri: https://github.com/grosser/parallel/wiki
31
31
  post_install_message:
32
32
  rdoc_options: []
@@ -43,7 +43,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
43
43
  - !ruby/object:Gem::Version
44
44
  version: '0'
45
45
  requirements: []
46
- rubygems_version: 3.2.16
46
+ rubygems_version: 3.1.6
47
47
  signing_key:
48
48
  specification_version: 4
49
49
  summary: Run any kind of code in parallel processes