picky 3.1.8 → 3.1.9

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.
Files changed (3) hide show
  1. data/lib/picky/cores.rb +46 -26
  2. data/spec/lib/cores_spec.rb +104 -27
  3. metadata +2 -2
data/lib/picky/cores.rb CHANGED
@@ -6,15 +6,17 @@ module Picky
6
6
  #
7
7
  class Cores # :nodoc:all
8
8
 
9
- # Pass it an ary or generator.
9
+ # Pass it an ary.
10
10
  #
11
- # generator = (1..10).each
12
- # forked generator, :max => 5 do |element|
11
+ # ary = (1..10).to_a
12
+ # forked ary, :max => 5 do |element|
13
13
  #
14
14
  # end
15
15
  #
16
16
  # Options include:
17
17
  # * max: Maximum # of processors to use. Default is all it can get.
18
+ # * amount: An exactly defined amount of processors to use.
19
+ # * randomly: Whether to use random order or not.
18
20
  #
19
21
  def self.forked elements, options = {}, &block
20
22
  return if elements.empty?
@@ -29,40 +31,58 @@ module Picky
29
31
 
30
32
  # Get the maximum number of processors.
31
33
  #
32
- max = max_processors options
33
- processing = 0
34
+ max = max_processors options
34
35
 
35
- loop do
36
- while processing < max
37
- # Get the next element
38
- #
39
- element = elements.shift
40
- break unless element
41
- processing += 1
36
+ # Decide whether to use forking.
37
+ #
38
+ if fork?(max)
39
+ processing = 0
42
40
 
43
- # Fork and yield.
44
- #
45
- Process.fork do
46
- sleep 0.05*processing
47
- block.call element
41
+ loop do
42
+ while processing < max
43
+ # Get the next element
44
+ #
45
+ element = elements.shift
46
+ break unless element
47
+ processing += 1
48
+
49
+ # Fork and yield.
50
+ #
51
+ Process.fork do
52
+ sleep 0.05*processing
53
+ block.call element
54
+ end
48
55
  end
49
- end
50
56
 
51
- # Block and wait for any child to finish.
52
- #
53
- begin
54
- Process.wait 0
55
- rescue Errno::ECHILD => e
56
- break
57
- ensure
58
- processing -= 1
57
+ # Block and wait for any child to finish.
58
+ #
59
+ begin
60
+ Process.wait 0
61
+ rescue Errno::ECHILD => e
62
+ break
63
+ ensure
64
+ processing -= 1
65
+ end
59
66
  end
67
+ else
68
+ elements.each &block
60
69
  end
61
70
 
62
71
  end
63
72
 
73
+ # Do not fork if there is just one processor,
74
+ # or as in Windows, if there isn't the
75
+ # possibility of forking.
76
+ #
77
+ def self.fork? max_processors
78
+ max_processors > 1 && Process.respond_to?(:fork)
79
+ end
80
+
64
81
  # Return the number of maximum usable processors.
65
82
  #
83
+ # Options
84
+ # max: The maximum amount of cores used.
85
+ #
66
86
  def self.max_processors options = {}
67
87
  options[:amount] || [number_of_cores, (options[:max] || Infinity)].min
68
88
  end
@@ -4,44 +4,121 @@ require 'spec_helper'
4
4
  describe Picky::Cores do
5
5
 
6
6
  describe ".forked" do
7
- before(:each) do
8
- Process.should_receive(:fork).any_number_of_times.and_yield
9
- end
10
- context "with array" do
11
- context "with block" do
12
- it "runs ok" do
13
- described_class.forked([1, 2]) do |e|
14
-
15
- end
7
+ context 'without fork' do
8
+ before(:each) do
9
+ Picky::Cores.stub! :fork? => false
10
+ end
11
+ it 'should not fork' do
12
+ Process.should_receive(:fork).never
13
+
14
+ described_class.forked([1,2]) do |element|
15
+
16
16
  end
17
- it "yields the elements" do
18
- result = []
19
- described_class.forked([1, 2]) do |e|
20
- result << e
21
- end
22
- result.should == [1, 2]
17
+ end
18
+ it 'should yield the two elements' do
19
+ result = []
20
+
21
+ described_class.forked([1,2]) do |element|
22
+ result << element
23
23
  end
24
+
25
+ result.should == [1,2]
24
26
  end
25
- context "without block" do
26
- it "fails" do
27
- lambda {
28
- described_class.forked [1, 2]
29
- }.should raise_error("Block argument needed when running Cores.forked")
27
+ it 'should yield the two elements' do
28
+ result = []
29
+
30
+ described_class.forked([1,2], randomly: true) do |element|
31
+ result << element
32
+ end
33
+
34
+ # This test remains like this because I
35
+ # like the stupidity of it.
36
+ #
37
+ if result == [1,2]
38
+ result.should == [1,2]
39
+ else
40
+ result.should == [2,1]
30
41
  end
31
42
  end
32
43
  end
33
- context "with empty array" do
34
- context "with block" do
35
- it "runs ok" do
36
- described_class.forked([]) do
44
+ context 'with forking' do
45
+ before(:each) do
46
+ Picky::Cores.stub! :fork? => true
47
+ Process.should_receive(:fork).any_number_of_times.and_yield
48
+ end
49
+ context "with array" do
50
+ context "with block" do
51
+ it "runs ok" do
52
+ # TODO Problematic test. Should not raise the first time
53
+ #
54
+ Process.should_receive(:wait).once.and_raise Errno::ECHILD.new
55
+
56
+ described_class.forked([1, 2]) do |e|
57
+
58
+ end
59
+ end
60
+ it "yields the elements" do
61
+ result = []
62
+
63
+ described_class.forked([1, 2]) do |e|
64
+ result << e
65
+ end
37
66
 
67
+ result.should == [1, 2]
68
+ end
69
+ it 'should not fork with amount option' do
70
+ Process.should_receive(:fork).never
71
+
72
+ described_class.forked([1,2], amount: 1) do |element|
73
+
74
+ end
75
+ end
76
+ it 'should not fork with max == 1 option' do
77
+ Process.should_receive(:fork).never
78
+
79
+ described_class.forked([1,2], max: 1) do |element|
80
+
81
+ end
82
+ end
83
+ end
84
+ context "without block" do
85
+ it "fails" do
86
+ lambda {
87
+ described_class.forked [1, 2]
88
+ }.should raise_error("Block argument needed when running Cores.forked")
38
89
  end
39
90
  end
40
91
  end
41
- context "without block" do
42
- it "runs ok" do
43
- described_class.forked []
92
+ context "with empty array" do
93
+ context "with block" do
94
+ it "runs ok" do
95
+ described_class.forked([]) do
96
+
97
+ end
98
+ end
44
99
  end
100
+ context "without block" do
101
+ it "runs ok" do
102
+ described_class.forked []
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ describe 'fork?' do
110
+ context 'with forking capabilities' do
111
+ before(:all) do
112
+ # Process.should_receive(:respond_to?).any_number_of_times.with(:fork).and_return true
113
+ end
114
+ it 'returns false' do
115
+ Picky::Cores.fork?(0).should == false
116
+ end
117
+ it 'returns false' do
118
+ Picky::Cores.fork?(1).should == false
119
+ end
120
+ it 'returns true' do
121
+ Picky::Cores.fork?(2).should == true
45
122
  end
46
123
  end
47
124
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: picky
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 3.1.8
5
+ version: 3.1.9
6
6
  platform: ruby
7
7
  authors:
8
8
  - Florian Hanke
@@ -32,7 +32,7 @@ dependencies:
32
32
  requirements:
33
33
  - - "="
34
34
  - !ruby/object:Gem::Version
35
- version: 3.1.8
35
+ version: 3.1.9
36
36
  type: :development
37
37
  version_requirements: *id002
38
38
  description: Fast Ruby semantic text search engine with comfortable single field interface.