forkify 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,10 @@
1
+ === 0.0.2 / 2009-06-29
2
+
3
+ * 2 bugfixes
4
+
5
+ * Forkify now works correctly returns array values on RedHat machines
6
+ * More tests!
7
+
1
8
  === 0.0.1 / 2009-06-23
2
9
 
3
10
  * 1 major enhancement
@@ -6,3 +6,4 @@ lib/forkify.rb
6
6
  test/test_forkify.rb
7
7
  examples/a.rb
8
8
  examples/b.rb
9
+ examples/c.rb
data/README.txt CHANGED
@@ -22,7 +22,7 @@
22
22
 
23
23
  == REQUIREMENTS:
24
24
 
25
- * None
25
+ * Testy - only for running the tests
26
26
 
27
27
  == INSTALL:
28
28
 
data/Rakefile CHANGED
@@ -4,12 +4,13 @@ require 'rubygems'
4
4
  require 'hoe'
5
5
  require './lib/forkify.rb'
6
6
 
7
- FORKIFY_VERSION = "0.0.1"
7
+ FORKIFY_VERSION = "0.0.2"
8
8
 
9
- Hoe.spec('forkify') do |p|
10
- p.version = FORKIFY_VERSION
11
- p.rubyforge_name = 'hinmanm'
12
- p.developer('Lee Hinman', 'lee@writequit.org')
9
+ Hoe.spec('forkify') do
10
+ version = FORKIFY_VERSION
11
+ developer('Lee Hinman', 'lee@writequit.org')
12
+ rubyforge_name = 'hinmanm'
13
13
  end
14
14
 
15
+
15
16
  # vim: syntax=Ruby
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # vim: set ts=2 sw=2 filetype=Ruby
3
+ #
4
+ # This example shows a problem with the current implementation of forkify:
5
+ # if a fork finishes work, it will still wait for the other forks to finish
6
+ # in the process pool before forking new processes for work.
7
+ #
8
+ # I hope to remedy this as soon as I figure out a good solution for it.
9
+
10
+ require 'forkify'
11
+
12
+ [1, 1, 1, 1, 5, 1].forkify(5) { |n| puts n; sleep(n); n }
13
+
14
+ # 0.04s user 0.06s system 1% cpu 6.031 total
15
+ # (would be possible to run in a little over 5)
@@ -1,9 +1,27 @@
1
- #require 'pp'
1
+ FORKIFY_DEBUG = false
2
+ require 'pp' if FORKIFY_DEBUG
2
3
 
3
4
  module Enumerable
5
+
6
+ #
7
+ # Forkify will process _block_'s actions using processes. If no number of processes is
8
+ # given, the default of 5 will be used. If there are less than _procs_ number of items
9
+ # in the +Enumerable+ type, less processes will be spawned.
10
+ #
11
+ # It should be noted that forkify will *always* return an +Array+ at this time, so be
12
+ # careful with +Hash+ objects.
13
+ #
14
+ # = Examples
15
+ #
16
+ # [1, 2, 3].forkify { |n| n*2 } => [2, 4, 6]
17
+ #
18
+ # {:a => 1, :b => 2, :c => 3}.forkify { |k, v| [v, k] } => [[1, :a], [2, :b], [3, :c]]
19
+ #
20
+ # 10.times.forkify(10) { sleep(1) } => [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] (runs for less than 2 seconds)
21
+ #
4
22
  def forkify procs = 5, &block
5
- #puts "Class: #{self.class}"
6
- if Array === self
23
+ puts "Forkify Class: #{self.class}" if FORKIFY_DEBUG
24
+ if self === Array
7
25
  items = self
8
26
  else
9
27
  begin
@@ -27,9 +45,9 @@ module Enumerable
27
45
  rpipes = []
28
46
 
29
47
  num_procs.times do |i|
30
- #puts "Fork # #{i}"
48
+ puts "Fork # #{i}" if FORKIFY_DEBUG
31
49
  r, w = IO.pipe
32
- #pp "r, w: #{r} #{w}"
50
+ pp "r, w: #{r} #{w}" if FORKIFY_DEBUG
33
51
  wpipes << w
34
52
  rpipes << r
35
53
  pid = fork
@@ -43,7 +61,7 @@ module Enumerable
43
61
  end
44
62
  w.write( Marshal.dump( result ))
45
63
  w.close
46
- exit
64
+ exit!
47
65
  end
48
66
 
49
67
  pids << pid
@@ -52,19 +70,27 @@ module Enumerable
52
70
 
53
71
  offset += num_procs
54
72
 
55
- #pp "Waiting for pids: #{pids}"
73
+ pp "Waiting for pids: #{pids.inspect}" if FORKIFY_DEBUG
56
74
  pids.each { |p| Process.waitpid(p) }
57
75
 
58
- datawaiting_pipes = Kernel.select(rpipes, wpipes, nil, 2)
59
- readwaiting_pipes = datawaiting_pipes[0]
60
- writewaiting_pipes = datawaiting_pipes[1]
61
- #pp "data: #{datawaiting_pipes}"
62
- #pp "read: #{readwaiting_pipes}"
63
- #pp "write: #{writewaiting_pipes}"
64
- unless readwaiting_pipes.size != writewaiting_pipes.size
65
- readwaiting_pipes.size.times do |i|
66
- r = readwaiting_pipes[i]
67
- w = writewaiting_pipes[i]
76
+ # 1 select version
77
+ #datawaiting_pipes = Kernel.select(rpipes, wpipes, nil, 2)
78
+ #readwaiting_pipes = datawaiting_pipes[0]
79
+ #writewaiting_pipes = datawaiting_pipes[1]
80
+
81
+ # Switch to 2 selects instead of 1
82
+ #readwaiting_pipes = Kernel.select(rpipes, nil, nil, 2)[0]
83
+ #writewaiting_pipes = Kernel.select(nil, wpipes, nil, 2)[1]
84
+
85
+ # Finally settled on going through the pipes instead of select for Linux bug
86
+ unless rpipes.size != wpipes.size
87
+ rpipes.size.times do |i|
88
+ r = rpipes[i]
89
+ w = wpipes[i]
90
+
91
+ pp "read: #{readwaiting_pipes}" if FORKIFY_DEBUG
92
+ pp "write: #{writewaiting_pipes}" if FORKIFY_DEBUG
93
+
68
94
  w.close
69
95
  data = ''
70
96
  while ( buf = r.read(8192) )
@@ -72,6 +98,7 @@ module Enumerable
72
98
  end
73
99
  result = Marshal.load( data )
74
100
  r.close
101
+ pp "Pushing result: #{result}" if FORKIFY_DEBUG
75
102
  results << result
76
103
  end
77
104
  end
@@ -1,18 +1,31 @@
1
- require "test/unit"
1
+ require "testy"
2
2
  require "forkify"
3
3
 
4
- class TestForkify < Test::Unit::TestCase
5
- def test_timings
4
+ Testy.testing 'forkify' do
5
+ test 'timings' do |t|
6
6
  time1 = Time.now
7
7
  r = [1, 2, 3].forkify(3) { |n| sleep(1) }
8
8
  time2 = Time.now
9
9
  # Assert that it took less than 3 seconds
10
- assert (time2 - time1) < 3
10
+ less_than_3 = ((time2 - time1) < 3)
11
+ t.check :timing, :expect => true, :actual => less_than_3
11
12
  end
12
13
 
13
- def test_array_results_returned_correctly
14
+ test 'array results' do |t|
14
15
  r = [1, 2, 3].forkify { |n| n * 2 }
15
- assert r == [2, 4, 6]
16
+ t.check :array_results, :expect => [2, 4, 6], :actual => r
16
17
  end
17
18
 
19
+ test 'hash results' do |t|
20
+ r = {:a => 1, :b => 2, :c => 3}.forkify { |k, v| [k, v*2] }
21
+ t.check :hash_contains_a, :expect => true, :actual => r.include?([:a, 2])
22
+ t.check :hash_contains_b, :expect => true, :actual => r.include?([:b, 4])
23
+ t.check :hash_contains_c, :expect => true, :actual => r.include?([:c, 6])
24
+ t.check :hash_length, :expect => 3, :actual => r.size
25
+ end
26
+
27
+ test 'array of nils' do |t|
28
+ r = [nil, nil].forkify { |n| n }
29
+ t.check :nil_array, :expect => [nil, nil], :actual => r
30
+ end
18
31
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forkify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lee Hinman
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-23 00:00:00 -06:00
12
+ date: 2009-06-29 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 2.0.0
23
+ version: 2.3.1
24
24
  version:
25
25
  description: |-
26
26
  forkify.rb makes it easy to process a bunch of data using 'n'
@@ -45,6 +45,7 @@ files:
45
45
  - test/test_forkify.rb
46
46
  - examples/a.rb
47
47
  - examples/b.rb
48
+ - examples/c.rb
48
49
  has_rdoc: true
49
50
  homepage: http://github.com/dakrone/forkify
50
51
  licenses: []
@@ -69,7 +70,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
69
70
  version:
70
71
  requirements: []
71
72
 
72
- rubyforge_project: hinmanm
73
+ rubyforge_project: forkify
73
74
  rubygems_version: 1.3.4
74
75
  signing_key:
75
76
  specification_version: 3