parallel 1.21.0 → 1.23.0

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: 7b8bb887652e89a339de17f31e8482aec8664426b2b12eb11566779f53153a56
4
+ data.tar.gz: e5fa1401f5748de7216a6d973d1ca1a2af514caeaec1dacafb153d2a5538334d
5
5
  SHA512:
6
- metadata.gz: 1f8a810c3b7fa77e8dd2b2539238b856b9b4ea40b5df49cf2cc4af2afbd2a73d9b6f34baab614c41e7b3b8bfe1917413bfbd014f647c5b4b96e7243d5433523d
7
- data.tar.gz: 0bef1c7dc19b4738e228985512ee6cce1915f67ee29161b743821f69366d561ed8c3c5cbd4d9e6829342108fe9f10329563770d1978a660a04c58c0d9e2c8461
6
+ metadata.gz: 481a4b04da349a2eb88cdcab724dc3c47efe757dcb61889a3105d0097fb3255ff6283470f6c2bc636c1bd053e274516fddfa33f8d362e8208f6f57638864ca48
7
+ data.tar.gz: 9093769c22e258cb921c1ab6ead1c7083fcc1d315b7bc268dff807c0fe1c4468b4316171e5f837283d7387ecdb01284f55763b60912c4bce7548aa9c869cc57b
@@ -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.23.0' # rubocop:disable Naming/ConstantName
4
4
  end
data/lib/parallel.rb CHANGED
@@ -1,11 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
  require 'rbconfig'
3
3
  require 'parallel/version'
4
- require 'parallel/processor_count'
5
4
 
6
5
  module Parallel
7
- extend ProcessorCount
8
-
9
6
  Stop = Object.new.freeze
10
7
 
11
8
  class DeadWorker < StandardError
@@ -264,6 +261,9 @@ module Parallel
264
261
  elsif options[:in_threads]
265
262
  method = :in_threads
266
263
  size = options[method]
264
+ elsif options[:in_ractors]
265
+ method = :in_ractors
266
+ size = options[method]
267
267
  else
268
268
  method = :in_processes
269
269
  if Process.respond_to?(:fork)
@@ -285,6 +285,8 @@ module Parallel
285
285
  work_direct(job_factory, options, &block)
286
286
  elsif method == :in_threads
287
287
  work_in_threads(job_factory, options.merge(count: size), &block)
288
+ elsif method == :in_ractors
289
+ work_in_ractors(job_factory, options.merge(count: size), &block)
288
290
  else
289
291
  work_in_processes(job_factory, options.merge(count: size), &block)
290
292
  end
@@ -302,6 +304,49 @@ module Parallel
302
304
  map(*args, &block).flatten(1)
303
305
  end
304
306
 
307
+ def filter_map(*args, &block)
308
+ map(*args, &block).compact
309
+ end
310
+
311
+ # Number of physical processor cores on the current system.
312
+ def physical_processor_count
313
+ @physical_processor_count ||= begin
314
+ ppc =
315
+ case RbConfig::CONFIG["target_os"]
316
+ when /darwin[12]/
317
+ IO.popen("/usr/sbin/sysctl -n hw.physicalcpu").read.to_i
318
+ when /linux/
319
+ cores = {} # unique physical ID / core ID combinations
320
+ phy = 0
321
+ File.read("/proc/cpuinfo").scan(/^physical id.*|^core id.*/) do |ln|
322
+ if ln.start_with?("physical")
323
+ phy = ln[/\d+/]
324
+ elsif ln.start_with?("core")
325
+ cid = "#{phy}:#{ln[/\d+/]}"
326
+ cores[cid] = true unless cores[cid]
327
+ end
328
+ end
329
+ cores.count
330
+ when /mswin|mingw/
331
+ require 'win32ole'
332
+ result_set = WIN32OLE.connect("winmgmts://").ExecQuery(
333
+ "select NumberOfCores from Win32_Processor"
334
+ )
335
+ result_set.to_enum.collect(&:NumberOfCores).reduce(:+)
336
+ else
337
+ processor_count
338
+ end
339
+ # fall back to logical count if physical info is invalid
340
+ ppc > 0 ? ppc : processor_count
341
+ end
342
+ end
343
+
344
+ # Number of processors seen by the OS, used for process scheduling
345
+ def processor_count
346
+ require 'etc'
347
+ @processor_count ||= Integer(ENV['PARALLEL_PROCESSOR_COUNT'] || Etc.nprocessors)
348
+ end
349
+
305
350
  def worker_number
306
351
  Thread.current[:parallel_worker_number]
307
352
  end
@@ -382,6 +427,72 @@ module Parallel
382
427
  exception || results
383
428
  end
384
429
 
430
+ def work_in_ractors(job_factory, options)
431
+ exception = nil
432
+ results = []
433
+ results_mutex = Mutex.new # arrays are not thread-safe on jRuby
434
+
435
+ callback = options[:ractor]
436
+ if block_given? || !callback
437
+ raise ArgumentError, "pass the code you want to execute as `ractor: [ClassName, :method_name]`"
438
+ end
439
+
440
+ # build
441
+ ractors = Array.new(options.fetch(:count)) do
442
+ Ractor.new do
443
+ loop do
444
+ got = receive
445
+ (klass, method_name), item, index = got
446
+ break if index == :break
447
+ begin
448
+ Ractor.yield [nil, klass.send(method_name, item), item, index]
449
+ rescue StandardError => e
450
+ Ractor.yield [e, nil, item, index]
451
+ end
452
+ end
453
+ end
454
+ end
455
+
456
+ # start
457
+ ractors.dup.each do |ractor|
458
+ if set = job_factory.next
459
+ item, index = set
460
+ instrument_start item, index, options
461
+ ractor.send [callback, item, index]
462
+ else
463
+ ractor.send([[nil, nil], nil, :break]) # stop the ractor
464
+ ractors.delete ractor
465
+ end
466
+ end
467
+
468
+ # replace with new items
469
+ while set = job_factory.next
470
+ item_next, index_next = set
471
+ done, (exception, result, item, index) = Ractor.select(*ractors)
472
+ if exception
473
+ ractors.delete done
474
+ break
475
+ end
476
+ instrument_finish item, index, result, options
477
+ results_mutex.synchronize { results[index] = (options[:preserve_results] == false ? nil : result) }
478
+
479
+ instrument_start item_next, index_next, options
480
+ done.send([callback, item_next, index_next])
481
+ end
482
+
483
+ # finish
484
+ ractors.each do |ractor|
485
+ (new_exception, result, item, index) = ractor.take
486
+ exception ||= new_exception
487
+ next if new_exception
488
+ instrument_finish item, index, result, options
489
+ results_mutex.synchronize { results[index] = (options[:preserve_results] == false ? nil : result) }
490
+ ractor.send([[nil, nil], nil, :break]) # stop the ractor
491
+ end
492
+
493
+ exception || results
494
+ end
495
+
385
496
  def work_in_processes(job_factory, options, &blk)
386
497
  workers = create_workers(job_factory, options, &blk)
387
498
  results = []
@@ -426,6 +537,7 @@ module Parallel
426
537
  end
427
538
  end
428
539
  end
540
+
429
541
  exception || results
430
542
  end
431
543
 
@@ -521,12 +633,20 @@ module Parallel
521
633
  end
522
634
 
523
635
  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
636
+ instrument_start(item, index, options)
527
637
  result = yield
528
- options[:mutex].synchronize { on_finish.call(item, index, result) } if on_finish
638
+ instrument_finish(item, index, result, options)
529
639
  result unless options[:preserve_results] == false
530
640
  end
641
+
642
+ def instrument_finish(item, index, result, options)
643
+ return unless on_finish = options[:finish]
644
+ options[:mutex].synchronize { on_finish.call(item, index, result) }
645
+ end
646
+
647
+ def instrument_start(item, index, options)
648
+ return unless on_start = options[:start]
649
+ options[:mutex].synchronize { on_start.call(item, index) }
650
+ end
531
651
  end
532
652
  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.23.0
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: 2023-04-18 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: michael@grosser.it
@@ -18,15 +18,14 @@ extra_rdoc_files: []
18
18
  files:
19
19
  - MIT-LICENSE.txt
20
20
  - lib/parallel.rb
21
- - lib/parallel/processor_count.rb
22
21
  - lib/parallel/version.rb
23
22
  homepage: https://github.com/grosser/parallel
24
23
  licenses:
25
24
  - MIT
26
25
  metadata:
27
26
  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
27
+ documentation_uri: https://github.com/grosser/parallel/blob/v1.23.0/Readme.md
28
+ source_code_uri: https://github.com/grosser/parallel/tree/v1.23.0
30
29
  wiki_uri: https://github.com/grosser/parallel/wiki
31
30
  post_install_message:
32
31
  rdoc_options: []
@@ -43,7 +42,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
43
42
  - !ruby/object:Gem::Version
44
43
  version: '0'
45
44
  requirements: []
46
- rubygems_version: 3.2.16
45
+ rubygems_version: 3.1.6
47
46
  signing_key:
48
47
  specification_version: 4
49
48
  summary: Run any kind of code in parallel processes
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'etc'
3
-
4
- module Parallel
5
- # TODO: inline this method into parallel.rb and kill physical_processor_count in next major release
6
- module ProcessorCount
7
- # Number of processors seen by the OS, used for process scheduling
8
- def processor_count
9
- @processor_count ||= Integer(ENV['PARALLEL_PROCESSOR_COUNT'] || Etc.nprocessors)
10
- end
11
-
12
- # Number of physical processor cores on the current system.
13
- def physical_processor_count
14
- @physical_processor_count ||= begin
15
- ppc =
16
- case RbConfig::CONFIG["target_os"]
17
- when /darwin[12]/
18
- IO.popen("/usr/sbin/sysctl -n hw.physicalcpu").read.to_i
19
- when /linux/
20
- cores = {} # unique physical ID / core ID combinations
21
- phy = 0
22
- IO.read("/proc/cpuinfo").scan(/^physical id.*|^core id.*/) do |ln|
23
- if ln.start_with?("physical")
24
- phy = ln[/\d+/]
25
- elsif ln.start_with?("core")
26
- cid = "#{phy}:#{ln[/\d+/]}"
27
- cores[cid] = true unless cores[cid]
28
- end
29
- end
30
- cores.count
31
- when /mswin|mingw/
32
- require 'win32ole'
33
- result_set = WIN32OLE.connect("winmgmts://").ExecQuery(
34
- "select NumberOfCores from Win32_Processor"
35
- )
36
- result_set.to_enum.collect(&:NumberOfCores).reduce(:+)
37
- else
38
- processor_count
39
- end
40
- # fall back to logical count if physical info is invalid
41
- ppc > 0 ? ppc : processor_count
42
- end
43
- end
44
- end
45
- end