threadify 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +40 -43
- data/README.erb +38 -0
- data/lib/threadify.rb +14 -8
- data/rakefile +231 -0
- data/sample/a.rb +10 -15
- data/sample/b.rb +14 -6
- data/threadify.gemspec +21 -21
- metadata +4 -5
- data/README.rb +0 -83
- data/gemspec.rb +0 -62
- data/install.rb +0 -214
data/README
CHANGED
@@ -4,6 +4,7 @@ NAME
|
|
4
4
|
SYNOPSIS
|
5
5
|
enumerable = %w( a b c d )
|
6
6
|
enumerable.threadify(2){ 'process this block using two worker threads' }
|
7
|
+
enumerable.threadify(:each_slice, 4){ 'process each slice of 4 in a thread' }
|
7
8
|
|
8
9
|
DESCRIPTION
|
9
10
|
threadify.rb makes it stupid easy to process a bunch of data using 'n'
|
@@ -14,6 +15,7 @@ INSTALL
|
|
14
15
|
|
15
16
|
URI
|
16
17
|
http://rubyforge.org/projects/codeforpeople
|
18
|
+
http://github.com/ahoward/threadify/
|
17
19
|
|
18
20
|
SAMPLES
|
19
21
|
|
@@ -21,39 +23,34 @@ SAMPLES
|
|
21
23
|
|
22
24
|
~ > cat sample/a.rb
|
23
25
|
|
24
|
-
require 'open-uri'
|
25
|
-
require 'yaml'
|
26
|
-
|
27
|
-
require 'rubygems'
|
28
26
|
require 'threadify'
|
29
27
|
|
28
|
+
require 'open-uri'
|
29
|
+
require 'yaml'
|
30
30
|
|
31
31
|
uris =
|
32
32
|
%w(
|
33
|
+
http://codeforpeople.com
|
34
|
+
http://drawohara.com
|
35
|
+
http://twitter.com/drawohara
|
36
|
+
http://github.com/ahoward/threadify/
|
33
37
|
http://google.com
|
34
|
-
http://yahoo.com
|
35
38
|
http://rubyforge.org
|
36
39
|
http://ruby-lang.org
|
37
|
-
http://
|
38
|
-
http://drawohara.com
|
39
|
-
http://codeforpeople.com
|
40
|
+
http://hypem.com
|
40
41
|
)
|
41
42
|
|
43
|
+
curl = lambda{|url| open(url){|socket| socket.read}}
|
42
44
|
|
43
45
|
time 'without threadify' do
|
44
|
-
uris.each
|
45
|
-
body = open(uri){|pipe| pipe.read}
|
46
|
-
end
|
46
|
+
uris.each{|uri| curl[uri]}
|
47
47
|
end
|
48
48
|
|
49
49
|
|
50
50
|
time 'with threadify' do
|
51
|
-
uris.threadify
|
52
|
-
body = open(uri){|pipe| pipe.read}
|
53
|
-
end
|
51
|
+
uris.threadify(uris.size){|uri| curl[uri]}
|
54
52
|
end
|
55
53
|
|
56
|
-
|
57
54
|
BEGIN {
|
58
55
|
def time label
|
59
56
|
a = Time.now.to_f
|
@@ -66,34 +63,22 @@ SAMPLES
|
|
66
63
|
|
67
64
|
~ > ruby sample/a.rb
|
68
65
|
|
69
|
-
/opt/local/lib/ruby/1.8/net/http.rb:560:in `initialize': getaddrinfo: nodename nor servname provided, or not known (SocketError)
|
70
|
-
from /opt/local/lib/ruby/1.8/net/http.rb:560:in `open'
|
71
|
-
from /opt/local/lib/ruby/1.8/net/http.rb:560:in `connect'
|
72
|
-
from /opt/local/lib/ruby/1.8/timeout.rb:48:in `timeout'
|
73
|
-
from /opt/local/lib/ruby/1.8/timeout.rb:76:in `timeout'
|
74
|
-
from /opt/local/lib/ruby/1.8/net/http.rb:560:in `connect'
|
75
|
-
from /opt/local/lib/ruby/1.8/net/http.rb:553:in `do_start'
|
76
|
-
from /opt/local/lib/ruby/1.8/net/http.rb:542:in `start'
|
77
|
-
from /opt/local/lib/ruby/1.8/open-uri.rb:242:in `open_http'
|
78
|
-
... 8 levels...
|
79
|
-
from sample/a.rb:21:in `each'
|
80
|
-
from sample/a.rb:21
|
81
|
-
from sample/a.rb:37:in `time'
|
82
|
-
from sample/a.rb:20
|
83
66
|
---
|
84
|
-
without threadify:
|
67
|
+
without threadify: 12.6283850669861
|
68
|
+
---
|
69
|
+
with threadify: 1.93842315673828
|
85
70
|
|
86
71
|
|
87
72
|
<========< sample/b.rb >========>
|
88
73
|
|
89
74
|
~ > cat sample/b.rb
|
90
75
|
|
91
|
-
require 'yaml'
|
92
|
-
|
93
|
-
require 'rubygems'
|
94
76
|
require 'threadify'
|
95
77
|
|
96
|
-
|
78
|
+
require 'yaml'
|
79
|
+
|
80
|
+
#size = Integer(ARGV.shift || (2 ** 20))
|
81
|
+
size = 64
|
97
82
|
|
98
83
|
haystack = Array.new(size){|i| i}
|
99
84
|
needle = 2 * (size / 3)
|
@@ -101,11 +86,19 @@ SAMPLES
|
|
101
86
|
a, b = 4, 2
|
102
87
|
|
103
88
|
time 'without threadify' do
|
104
|
-
a =
|
89
|
+
a =
|
90
|
+
haystack.each do |value|
|
91
|
+
break value if value == needle
|
92
|
+
sleep(rand) # mimic work
|
93
|
+
end
|
105
94
|
end
|
106
95
|
|
107
96
|
time 'with threadify' do
|
108
|
-
b =
|
97
|
+
b =
|
98
|
+
haystack.threadify(:each_slice, size / 8) do |slice|
|
99
|
+
slice.each{|value| threadify! value if value == needle}
|
100
|
+
sleep(rand) # mimic work
|
101
|
+
end
|
109
102
|
end
|
110
103
|
|
111
104
|
raise if a != b
|
@@ -125,19 +118,23 @@ SAMPLES
|
|
125
118
|
~ > ruby sample/b.rb
|
126
119
|
|
127
120
|
---
|
128
|
-
without threadify:
|
121
|
+
without threadify: 22.8657438755035
|
129
122
|
---
|
130
|
-
with threadify: 0.
|
123
|
+
with threadify: 0.967911005020142
|
131
124
|
---
|
132
|
-
:needle:
|
133
|
-
:a:
|
134
|
-
:b:
|
125
|
+
:needle: 42
|
126
|
+
:a: 42
|
127
|
+
:b: 42
|
128
|
+
|
135
129
|
|
136
130
|
|
137
131
|
|
138
132
|
HISTORY
|
139
|
-
1.
|
140
|
-
-
|
133
|
+
1.1.0
|
134
|
+
- added ability to specify arbitrary iterator (not only each)
|
135
|
+
[0,1,2,3].threadify(:each_slice, 2){|ary| ary}
|
136
|
+
- update samples
|
137
|
+
- auto include enumerator
|
141
138
|
|
142
139
|
0.0.3
|
143
140
|
- added ability to short-circuit the parallel processing, a.k.a to 'break'
|
data/README.erb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
NAME
|
2
|
+
threadify.rb
|
3
|
+
|
4
|
+
SYNOPSIS
|
5
|
+
enumerable = %w( a b c d )
|
6
|
+
enumerable.threadify(2){ 'process this block using two worker threads' }
|
7
|
+
enumerable.threadify(:each_slice, 4){ 'process each slice of 4 in a thread' }
|
8
|
+
|
9
|
+
DESCRIPTION
|
10
|
+
threadify.rb makes it stupid easy to process a bunch of data using 'n'
|
11
|
+
worker threads
|
12
|
+
|
13
|
+
INSTALL
|
14
|
+
gem install threadify
|
15
|
+
|
16
|
+
URI
|
17
|
+
http://rubyforge.org/projects/codeforpeople
|
18
|
+
http://github.com/ahoward/threadify/
|
19
|
+
|
20
|
+
SAMPLES
|
21
|
+
<%= samples %>
|
22
|
+
|
23
|
+
|
24
|
+
HISTORY
|
25
|
+
1.1.0
|
26
|
+
- added ability to specify arbitrary iterator (not only each)
|
27
|
+
[0,1,2,3].threadify(:each_slice, 2){|ary| ary}
|
28
|
+
- update samples
|
29
|
+
- auto include enumerator
|
30
|
+
|
31
|
+
0.0.3
|
32
|
+
- added ability to short-circuit the parallel processing, a.k.a to 'break'
|
33
|
+
from threadify
|
34
|
+
|
35
|
+
0.0.2
|
36
|
+
- don't use thread.exit, just let the thread die naturally
|
37
|
+
- add version to Threadify module
|
38
|
+
- comments ;-)
|
data/lib/threadify.rb
CHANGED
@@ -1,36 +1,43 @@
|
|
1
1
|
module Threadify
|
2
|
-
VERSION = '1.
|
2
|
+
Threadify::VERSION = '1.1.0' unless defined?(Threadify::VERSION)
|
3
3
|
def Threadify.version() Threadify::VERSION end
|
4
4
|
|
5
5
|
require 'thread'
|
6
|
+
require 'enumerator'
|
6
7
|
|
7
8
|
@threads = 8
|
8
9
|
@abort_on_exception = true
|
10
|
+
@strategy = [:each]
|
9
11
|
|
10
12
|
class << self
|
11
13
|
attr_accessor :threads
|
12
14
|
attr_accessor :abort_on_exception
|
15
|
+
attr_accessor :strategy
|
13
16
|
end
|
14
17
|
|
15
18
|
class Error < ::StandardError; end
|
16
19
|
end
|
17
20
|
|
18
21
|
module Enumerable
|
19
|
-
def threadify(
|
22
|
+
def threadify(*args, &block)
|
20
23
|
# setup
|
21
24
|
#
|
22
|
-
opts =
|
23
|
-
|
25
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
26
|
+
opts.keys.each{|key| opts[key.to_s.to_sym] = opts.delete(key)}
|
27
|
+
opts[:threads] ||= (Numeric === args.first ? args.shift : Threadify.threads)
|
28
|
+
opts[:strategy] ||= (args.empty? ? Threadify.strategy : args)
|
29
|
+
|
30
|
+
threads = Integer(opts[:threads])
|
31
|
+
strategy = opts[:strategy]
|
24
32
|
done = Object.new.freeze
|
25
33
|
nothing = done
|
26
|
-
#jobs = Array.new(threads).map{ Queue.new }
|
27
34
|
jobs = Array.new(threads).map{ [] }
|
28
35
|
top = Thread.current
|
29
36
|
|
30
37
|
# produce jobs
|
31
38
|
#
|
32
39
|
i = 0
|
33
|
-
|
40
|
+
send(*strategy){|*args| jobs[i % threads].push([args, i]); i += 1}
|
34
41
|
threads.times{|i| jobs[i].push(done)}
|
35
42
|
|
36
43
|
# setup consumer list
|
@@ -67,7 +74,6 @@ module Enumerable
|
|
67
74
|
catch(:threadify) do
|
68
75
|
loop{
|
69
76
|
break if caught
|
70
|
-
#job = jobsi.pop
|
71
77
|
job = jobsi.shift
|
72
78
|
break if job == done
|
73
79
|
args = job.first
|
@@ -78,8 +84,8 @@ module Enumerable
|
|
78
84
|
|
79
85
|
|
80
86
|
unless nothing == thrown
|
81
|
-
args, i = job
|
82
87
|
thrownq.push [i, thrown]
|
88
|
+
args, i = job
|
83
89
|
end
|
84
90
|
end
|
85
91
|
end
|
data/rakefile
ADDED
@@ -0,0 +1,231 @@
|
|
1
|
+
|
2
|
+
This.rubyforge_project = 'codeforpeople'
|
3
|
+
This.author = "Ara T. Howard"
|
4
|
+
This.email = "ara.t.howard@gmail.com"
|
5
|
+
This.homepage = "http://github.com/ahoward/#{ This.lib }/tree/master"
|
6
|
+
|
7
|
+
|
8
|
+
task :default do
|
9
|
+
puts(Rake::Task.tasks.map{|task| task.name} - ['default'])
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
task :gemspec do
|
14
|
+
ignore_extensions = 'git', 'svn', 'tmp', /sw./, 'bak', 'gem'
|
15
|
+
ignore_directories = 'pkg'
|
16
|
+
|
17
|
+
shiteless =
|
18
|
+
lambda do |list|
|
19
|
+
list.delete_if do |entry|
|
20
|
+
next unless test(?e, entry)
|
21
|
+
extension = File.basename(entry).split(%r/[.]/).last
|
22
|
+
ignore_extensions.any?{|ext| ext === extension}
|
23
|
+
end
|
24
|
+
list.delete_if do |entry|
|
25
|
+
next unless test(?d, entry)
|
26
|
+
dirname = File.expand_path(entry)
|
27
|
+
ignore_directories.any?{|dir| File.expand_path(dir) == dirname}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
lib = This.lib
|
32
|
+
version = This.version
|
33
|
+
files = shiteless[Dir::glob("**/**")]
|
34
|
+
executables = shiteless[Dir::glob("bin/*")].map{|exe| File.basename(exe)}
|
35
|
+
has_rdoc = true #File.exist?('doc')
|
36
|
+
test_files = "test/#{ lib }.rb" if File.file?("test/#{ lib }.rb")
|
37
|
+
|
38
|
+
extensions = This.extensions
|
39
|
+
if extensions.nil?
|
40
|
+
%w( Makefile configure extconf.rb ).each do |ext|
|
41
|
+
extensions << ext if File.exists?(ext)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
extensions = [extensions].flatten.compact
|
45
|
+
|
46
|
+
template =
|
47
|
+
if test(?e, 'gemspec.erb')
|
48
|
+
Template{ IO.read('gemspec.erb') }
|
49
|
+
else
|
50
|
+
Template {
|
51
|
+
<<-__
|
52
|
+
## #{ lib }.gemspec
|
53
|
+
#
|
54
|
+
|
55
|
+
Gem::Specification::new do |spec|
|
56
|
+
spec.name = #{ lib.inspect }
|
57
|
+
spec.version = #{ version.inspect }
|
58
|
+
spec.platform = Gem::Platform::RUBY
|
59
|
+
spec.summary = #{ lib.inspect }
|
60
|
+
|
61
|
+
spec.files = #{ files.inspect }
|
62
|
+
spec.executables = #{ executables.inspect }
|
63
|
+
|
64
|
+
spec.require_path = "lib"
|
65
|
+
|
66
|
+
spec.has_rdoc = #{ has_rdoc.inspect }
|
67
|
+
spec.test_files = #{ test_files.inspect }
|
68
|
+
#spec.add_dependency 'lib', '>= version'
|
69
|
+
#spec.add_dependency 'fattr'
|
70
|
+
|
71
|
+
spec.extensions.push(*#{ extensions.inspect })
|
72
|
+
|
73
|
+
spec.rubyforge_project = #{ This.rubyforge_project.inspect }
|
74
|
+
spec.author = #{ This.author.inspect }
|
75
|
+
spec.email = #{ This.email.inspect }
|
76
|
+
spec.homepage = #{ This.homepage.inspect }
|
77
|
+
end
|
78
|
+
__
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
open("#{ lib }.gemspec", "w"){|fd| fd.puts template}
|
83
|
+
This.gemspec = "#{ lib }.gemspec"
|
84
|
+
end
|
85
|
+
|
86
|
+
task :gem => [:clean, :gemspec] do
|
87
|
+
#gem = File.join(This.pkgdir, "#{ lib }.gemspec")
|
88
|
+
#open("#{ This.pkgdir }/#{ lib }.gemspec", "w"){|fd| fd.puts template}
|
89
|
+
#before = Dir['*.gem']
|
90
|
+
#cmd = "gem build #{ This.lib }.gemspec"
|
91
|
+
#`#{ cmd } 2>&1`
|
92
|
+
#after = Dir['*.gem']
|
93
|
+
#gems = [after - before]
|
94
|
+
#p gems
|
95
|
+
|
96
|
+
Fu.mkdir_p This.pkgdir
|
97
|
+
Dir.chdir(This.pkgdir) do
|
98
|
+
cmd = "gem build ../#{ This.gemspec }"
|
99
|
+
`#{ cmd } 2>&1`
|
100
|
+
gem = Dir['*.gem'].first or 'abort no gem!'
|
101
|
+
This.gem = File.basename(gem)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
task :readme do
|
107
|
+
samples = ''
|
108
|
+
prompt = '~ > '
|
109
|
+
lib = This.lib
|
110
|
+
version = This.version
|
111
|
+
|
112
|
+
Dir['sample*/*'].sort.each do |sample|
|
113
|
+
samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
|
114
|
+
|
115
|
+
cmd = "cat #{ sample }"
|
116
|
+
samples << Util.indent(prompt + cmd, 2) << "\n\n"
|
117
|
+
samples << Util.indent(`#{ cmd }`, 4) << "\n"
|
118
|
+
|
119
|
+
cmd = "ruby #{ sample }"
|
120
|
+
samples << Util.indent(prompt + cmd, 2) << "\n\n"
|
121
|
+
|
122
|
+
cmd = "ruby -e'STDOUT.sync=true; exec %(ruby -Ilib #{ sample })'"
|
123
|
+
samples << Util.indent(`#{ cmd } 2>&1`, 4) << "\n"
|
124
|
+
end
|
125
|
+
|
126
|
+
template =
|
127
|
+
if test(?e, 'readme.erb')
|
128
|
+
Template{ IO.read('readme.erb') }
|
129
|
+
else
|
130
|
+
Template {
|
131
|
+
<<-__
|
132
|
+
NAME
|
133
|
+
#{ lib }
|
134
|
+
|
135
|
+
DESCRIPTION
|
136
|
+
|
137
|
+
INSTALL
|
138
|
+
gem install #{ lib }
|
139
|
+
|
140
|
+
SAMPLES
|
141
|
+
#{ samples }
|
142
|
+
__
|
143
|
+
}
|
144
|
+
end
|
145
|
+
|
146
|
+
open("README", "w"){|fd| fd.puts template}
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
task :clean do
|
151
|
+
Dir[File.join(This.pkgdir, '**/**')].each{|entry| Fu.rm_rf(entry)}
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
task :release => [:clean, :gemspec, :gem] do
|
156
|
+
gems = Dir[File.join(This.pkgdir, '*.gem')].flatten
|
157
|
+
raise "which one? : #{ gems.inspect }" if gems.size > 1
|
158
|
+
raise "no gems?" if gems.size < 1
|
159
|
+
cmd = "rubyforge login && rubyforge add_release #{ This.rubyforge_project } #{ This.lib } #{ This.version } #{ This.pkgdir }/#{ This.gem }"
|
160
|
+
puts cmd
|
161
|
+
system cmd
|
162
|
+
end
|
163
|
+
|
164
|
+
|
165
|
+
|
166
|
+
|
167
|
+
|
168
|
+
BEGIN {
|
169
|
+
$VERBOSE = nil
|
170
|
+
|
171
|
+
require 'ostruct'
|
172
|
+
require 'erb'
|
173
|
+
require 'fileutils'
|
174
|
+
|
175
|
+
Fu = FileUtils
|
176
|
+
|
177
|
+
This = OpenStruct.new
|
178
|
+
|
179
|
+
This.file = File.expand_path(__FILE__)
|
180
|
+
This.dir = File.dirname(This.file)
|
181
|
+
This.pkgdir = File.join(This.dir, 'pkg')
|
182
|
+
|
183
|
+
lib = ENV['LIB']
|
184
|
+
unless lib
|
185
|
+
lib = File.basename(Dir.pwd)
|
186
|
+
end
|
187
|
+
This.lib = lib
|
188
|
+
|
189
|
+
version = ENV['VERSION']
|
190
|
+
unless version
|
191
|
+
name = lib.capitalize
|
192
|
+
require "./lib/#{ lib }"
|
193
|
+
version = eval(name).send(:version)
|
194
|
+
end
|
195
|
+
This.version = version
|
196
|
+
|
197
|
+
abort('no lib') unless This.lib
|
198
|
+
abort('no version') unless This.version
|
199
|
+
|
200
|
+
module Util
|
201
|
+
def indent(s, n = 2)
|
202
|
+
s = unindent(s)
|
203
|
+
ws = ' ' * n
|
204
|
+
s.gsub(%r/^/, ws)
|
205
|
+
end
|
206
|
+
|
207
|
+
def unindent(s)
|
208
|
+
indent = nil
|
209
|
+
s.each do |line|
|
210
|
+
next if line =~ %r/^\s*$/
|
211
|
+
indent = line[%r/^\s*/] and break
|
212
|
+
end
|
213
|
+
indent ? s.gsub(%r/^#{ indent }/, "") : s
|
214
|
+
end
|
215
|
+
extend self
|
216
|
+
end
|
217
|
+
|
218
|
+
class Template
|
219
|
+
def initialize(&block)
|
220
|
+
@block = block
|
221
|
+
@template = block.call.to_s
|
222
|
+
end
|
223
|
+
def expand(b=nil)
|
224
|
+
ERB.new(Util.unindent(@template)).result(b||@block)
|
225
|
+
end
|
226
|
+
alias_method 'to_s', 'expand'
|
227
|
+
end
|
228
|
+
def Template(*args, &block) Template.new(*args, &block) end
|
229
|
+
|
230
|
+
Dir.chdir(This.dir)
|
231
|
+
}
|
data/sample/a.rb
CHANGED
@@ -1,36 +1,31 @@
|
|
1
|
-
require 'open-uri'
|
2
|
-
require 'yaml'
|
3
|
-
|
4
|
-
require 'rubygems'
|
5
1
|
require 'threadify'
|
6
2
|
|
3
|
+
require 'open-uri'
|
4
|
+
require 'yaml'
|
7
5
|
|
8
6
|
uris =
|
9
7
|
%w(
|
8
|
+
http://codeforpeople.com
|
9
|
+
http://drawohara.com
|
10
|
+
http://twitter.com/drawohara
|
11
|
+
http://github.com/ahoward/threadify/
|
10
12
|
http://google.com
|
11
|
-
http://yahoo.com
|
12
13
|
http://rubyforge.org
|
13
14
|
http://ruby-lang.org
|
14
|
-
http://
|
15
|
-
http://drawohara.com
|
16
|
-
http://codeforpeople.com
|
15
|
+
http://hypem.com
|
17
16
|
)
|
18
17
|
|
18
|
+
curl = lambda{|url| open(url){|socket| socket.read}}
|
19
19
|
|
20
20
|
time 'without threadify' do
|
21
|
-
uris.each
|
22
|
-
body = open(uri){|pipe| pipe.read}
|
23
|
-
end
|
21
|
+
uris.each{|uri| curl[uri]}
|
24
22
|
end
|
25
23
|
|
26
24
|
|
27
25
|
time 'with threadify' do
|
28
|
-
uris.threadify
|
29
|
-
body = open(uri){|pipe| pipe.read}
|
30
|
-
end
|
26
|
+
uris.threadify(uris.size){|uri| curl[uri]}
|
31
27
|
end
|
32
28
|
|
33
|
-
|
34
29
|
BEGIN {
|
35
30
|
def time label
|
36
31
|
a = Time.now.to_f
|
data/sample/b.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
1
|
require 'threadify'
|
5
2
|
|
6
|
-
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
#size = Integer(ARGV.shift || (2 ** 20))
|
6
|
+
size = 64
|
7
7
|
|
8
8
|
haystack = Array.new(size){|i| i}
|
9
9
|
needle = 2 * (size / 3)
|
@@ -11,11 +11,19 @@ needle = 2 * (size / 3)
|
|
11
11
|
a, b = 4, 2
|
12
12
|
|
13
13
|
time 'without threadify' do
|
14
|
-
a =
|
14
|
+
a =
|
15
|
+
haystack.each do |value|
|
16
|
+
break value if value == needle
|
17
|
+
sleep(rand) # mimic work
|
18
|
+
end
|
15
19
|
end
|
16
20
|
|
17
21
|
time 'with threadify' do
|
18
|
-
b =
|
22
|
+
b =
|
23
|
+
haystack.threadify(:each_slice, size / 8) do |slice|
|
24
|
+
slice.each{|value| threadify! value if value == needle}
|
25
|
+
sleep(rand) # mimic work
|
26
|
+
end
|
19
27
|
end
|
20
28
|
|
21
29
|
raise if a != b
|
data/threadify.gemspec
CHANGED
@@ -1,26 +1,26 @@
|
|
1
|
-
|
1
|
+
## threadify.gemspec
|
2
|
+
#
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
Gem::Specification::new do |spec|
|
5
|
+
spec.name = "threadify"
|
6
|
+
spec.version = "1.1.0"
|
7
|
+
spec.platform = Gem::Platform::RUBY
|
8
|
+
spec.summary = "threadify"
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
spec.files = ["lib", "lib/threadify.rb", "rakefile", "README", "README.erb", "sample", "sample/a.rb", "sample/b.rb", "threadify.gemspec"]
|
11
|
+
spec.executables = []
|
12
|
+
|
13
|
+
spec.require_path = "lib"
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
spec.has_rdoc = true
|
16
|
+
spec.test_files = nil
|
17
|
+
#spec.add_dependency 'lib', '>= version'
|
18
|
+
#spec.add_dependency 'fattr'
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
spec.rubyforge_project = 'codeforpeople'
|
22
|
-
spec.author = "Ara T. Howard"
|
23
|
-
spec.email = "ara.t.howard@gmail.com"
|
24
|
-
spec.homepage = "http://github.com/ahoward/threadify/tree/master"
|
25
|
-
end
|
20
|
+
spec.extensions.push(*[])
|
26
21
|
|
22
|
+
spec.rubyforge_project = "codeforpeople"
|
23
|
+
spec.author = "Ara T. Howard"
|
24
|
+
spec.email = "ara.t.howard@gmail.com"
|
25
|
+
spec.homepage = "http://github.com/ahoward/threadify/tree/master"
|
26
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: threadify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ara T. Howard
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-06-
|
12
|
+
date: 2009-06-09 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -22,12 +22,11 @@ extensions: []
|
|
22
22
|
extra_rdoc_files: []
|
23
23
|
|
24
24
|
files:
|
25
|
-
- gemspec.rb
|
26
|
-
- install.rb
|
27
25
|
- lib
|
28
26
|
- lib/threadify.rb
|
27
|
+
- rakefile
|
29
28
|
- README
|
30
|
-
- README.
|
29
|
+
- README.erb
|
31
30
|
- sample
|
32
31
|
- sample/a.rb
|
33
32
|
- sample/b.rb
|
data/README.rb
DELETED
@@ -1,83 +0,0 @@
|
|
1
|
-
#! /usr/bin/env ruby
|
2
|
-
|
3
|
-
template = <<-__
|
4
|
-
NAME
|
5
|
-
threadify.rb
|
6
|
-
|
7
|
-
SYNOPSIS
|
8
|
-
enumerable = %w( a b c d )
|
9
|
-
enumerable.threadify(2){ 'process this block using two worker threads' }
|
10
|
-
|
11
|
-
DESCRIPTION
|
12
|
-
threadify.rb makes it stupid easy to process a bunch of data using 'n'
|
13
|
-
worker threads
|
14
|
-
|
15
|
-
INSTALL
|
16
|
-
gem install threadify
|
17
|
-
|
18
|
-
URI
|
19
|
-
http://rubyforge.org/projects/codeforpeople
|
20
|
-
|
21
|
-
SAMPLES
|
22
|
-
<%= samples %>
|
23
|
-
|
24
|
-
HISTORY
|
25
|
-
1.0.0
|
26
|
-
- adjust threadify to yield objects exactly like Enumerable#each
|
27
|
-
|
28
|
-
0.0.3
|
29
|
-
- added ability to short-circuit the parallel processing, a.k.a to 'break'
|
30
|
-
from threadify
|
31
|
-
|
32
|
-
0.0.2
|
33
|
-
- don't use thread.exit, just let the thread die naturally
|
34
|
-
- add version to Threadify module
|
35
|
-
- comments ;-)
|
36
|
-
__
|
37
|
-
|
38
|
-
|
39
|
-
require 'erb'
|
40
|
-
require 'pathname'
|
41
|
-
|
42
|
-
$VERBOSE=nil
|
43
|
-
|
44
|
-
def indent(s, n = 2)
|
45
|
-
s = unindent(s)
|
46
|
-
ws = ' ' * n
|
47
|
-
s.gsub(%r/^/, ws)
|
48
|
-
end
|
49
|
-
|
50
|
-
def unindent(s)
|
51
|
-
indent = nil
|
52
|
-
s.each do |line|
|
53
|
-
next if line =~ %r/^\s*$/
|
54
|
-
indent = line[%r/^\s*/] and break
|
55
|
-
end
|
56
|
-
indent ? s.gsub(%r/^#{ indent }/, "") : s
|
57
|
-
end
|
58
|
-
|
59
|
-
samples = ''
|
60
|
-
prompt = '~ > '
|
61
|
-
|
62
|
-
Dir.chdir(File.dirname(__FILE__))
|
63
|
-
|
64
|
-
Dir['sample*/*'].sort.each do |sample|
|
65
|
-
samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
|
66
|
-
|
67
|
-
cmd = "cat #{ sample }"
|
68
|
-
samples << indent(prompt + cmd, 2) << "\n\n"
|
69
|
-
samples << indent(`#{ cmd }`, 4) << "\n"
|
70
|
-
|
71
|
-
cmd = "ruby #{ sample }"
|
72
|
-
samples << indent(prompt + cmd, 2) << "\n\n"
|
73
|
-
|
74
|
-
cmd = "ruby -e'STDOUT.sync=true; exec %(ruby -Ilib #{ sample })'"
|
75
|
-
#cmd = "ruby -Ilib #{ sample }"
|
76
|
-
samples << indent(`#{ cmd } 2>&1`, 4) << "\n"
|
77
|
-
end
|
78
|
-
|
79
|
-
erb = ERB.new(unindent(template))
|
80
|
-
result = erb.result(binding)
|
81
|
-
#open('README', 'w'){|fd| fd.write result}
|
82
|
-
#puts unindent(result)
|
83
|
-
puts result
|
data/gemspec.rb
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
#! /usr/bin/env ruby
|
2
|
-
|
3
|
-
lib, version, *ignored = ARGV
|
4
|
-
|
5
|
-
unless lib
|
6
|
-
lib = File.basename(Dir.pwd)
|
7
|
-
end
|
8
|
-
|
9
|
-
unless version
|
10
|
-
mod = lib.capitalize
|
11
|
-
require "./lib/#{ lib }"
|
12
|
-
version = eval(mod).send(:version)
|
13
|
-
end
|
14
|
-
|
15
|
-
abort('no lib') unless lib
|
16
|
-
abort('no version') unless version
|
17
|
-
|
18
|
-
puts "### gemspec: #{ lib }-#{ version }"
|
19
|
-
|
20
|
-
$VERBOSE = nil
|
21
|
-
|
22
|
-
shiteless = lambda{|list| list.delete_if{|file| file =~ %r/\.(git|svn|tmp|sw.|bak)$/}}
|
23
|
-
|
24
|
-
files = shiteless[Dir::glob("**/**")]
|
25
|
-
executables = shiteless[Dir::glob("bin/*")].map{|exe| File.basename(exe)}
|
26
|
-
has_rdoc = true #File.exist?('doc')
|
27
|
-
test_files = "test/#{ lib }.rb" if File.file?("test/#{ lib }.rb")
|
28
|
-
|
29
|
-
extensions = []
|
30
|
-
%w( Makefile configure extconf.rb rakefile Rakefile mkrf_conf ).each do |ext|
|
31
|
-
extensions << ext if File.exists?(ext)
|
32
|
-
end
|
33
|
-
|
34
|
-
template = <<-__
|
35
|
-
|
36
|
-
Gem::Specification::new do |spec|
|
37
|
-
spec.name = #{ lib.inspect }
|
38
|
-
spec.version = #{ version.inspect }
|
39
|
-
spec.platform = Gem::Platform::RUBY
|
40
|
-
spec.summary = #{ lib.inspect }
|
41
|
-
|
42
|
-
spec.files = #{ files.inspect }
|
43
|
-
spec.executables = #{ executables.inspect }
|
44
|
-
|
45
|
-
spec.require_path = "lib"
|
46
|
-
|
47
|
-
spec.has_rdoc = #{ has_rdoc.inspect }
|
48
|
-
spec.test_files = #{ test_files.inspect }
|
49
|
-
#spec.add_dependency 'lib', '>= version'
|
50
|
-
#spec.add_dependency 'fattr'
|
51
|
-
|
52
|
-
spec.extensions.push(*#{ extensions.inspect })
|
53
|
-
|
54
|
-
spec.rubyforge_project = 'codeforpeople'
|
55
|
-
spec.author = "Ara T. Howard"
|
56
|
-
spec.email = "ara.t.howard@gmail.com"
|
57
|
-
spec.homepage = "http://github.com/ahoward/#{ lib }/tree/master"
|
58
|
-
end
|
59
|
-
|
60
|
-
__
|
61
|
-
|
62
|
-
puts template
|
data/install.rb
DELETED
@@ -1,214 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'rbconfig'
|
3
|
-
require 'find'
|
4
|
-
require 'ftools'
|
5
|
-
require 'tempfile'
|
6
|
-
include Config
|
7
|
-
|
8
|
-
LIBDIR = "lib"
|
9
|
-
LIBDIR_MODE = 0644
|
10
|
-
|
11
|
-
BINDIR = "bin"
|
12
|
-
BINDIR_MODE = 0755
|
13
|
-
|
14
|
-
|
15
|
-
$srcdir = CONFIG["srcdir"]
|
16
|
-
$version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
|
17
|
-
$libdir = File.join(CONFIG["libdir"], "ruby", $version)
|
18
|
-
$archdir = File.join($libdir, CONFIG["arch"])
|
19
|
-
$site_libdir = $:.find {|x| x =~ /site_ruby$/}
|
20
|
-
$bindir = CONFIG["bindir"] || CONFIG['BINDIR']
|
21
|
-
$ruby_install_name = CONFIG['ruby_install_name'] || CONFIG['RUBY_INSTALL_NAME'] || 'ruby'
|
22
|
-
$ruby_ext = CONFIG['EXEEXT'] || ''
|
23
|
-
$ruby = File.join($bindir, ($ruby_install_name + $ruby_ext))
|
24
|
-
|
25
|
-
if !$site_libdir
|
26
|
-
$site_libdir = File.join($libdir, "site_ruby")
|
27
|
-
elsif $site_libdir !~ %r/#{Regexp.quote($version)}/
|
28
|
-
$site_libdir = File.join($site_libdir, $version)
|
29
|
-
end
|
30
|
-
|
31
|
-
def install_rb(srcdir=nil, destdir=nil, mode=nil, bin=nil)
|
32
|
-
#{{{
|
33
|
-
path = []
|
34
|
-
dir = []
|
35
|
-
Find.find(srcdir) do |f|
|
36
|
-
next unless FileTest.file?(f)
|
37
|
-
next if (f = f[srcdir.length+1..-1]) == nil
|
38
|
-
next if (/CVS$/ =~ File.dirname(f))
|
39
|
-
next if (/\.svn/ =~ File.dirname(f))
|
40
|
-
next if f =~ %r/\.lnk/
|
41
|
-
next if f =~ %r/\.svn/
|
42
|
-
next if f =~ %r/\.swp/
|
43
|
-
next if f =~ %r/\.svn/
|
44
|
-
path.push f
|
45
|
-
dir |= [File.dirname(f)]
|
46
|
-
end
|
47
|
-
for f in dir
|
48
|
-
next if f == "."
|
49
|
-
next if f == "CVS"
|
50
|
-
File::makedirs(File.join(destdir, f))
|
51
|
-
end
|
52
|
-
for f in path
|
53
|
-
next if (/\~$/ =~ f)
|
54
|
-
next if (/^\./ =~ File.basename(f))
|
55
|
-
unless bin
|
56
|
-
File::install(File.join(srcdir, f), File.join(destdir, f), mode, true)
|
57
|
-
else
|
58
|
-
from = File.join(srcdir, f)
|
59
|
-
to = File.join(destdir, f)
|
60
|
-
shebangify(from) do |sf|
|
61
|
-
$deferr.print from, " -> ", File::catname(from, to), "\n"
|
62
|
-
$deferr.printf "chmod %04o %s\n", mode, to
|
63
|
-
File::install(sf, to, mode, false)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
#}}}
|
68
|
-
end
|
69
|
-
def shebangify f
|
70
|
-
#{{{
|
71
|
-
open(f) do |fd|
|
72
|
-
buf = fd.read 42
|
73
|
-
if buf =~ %r/^\s*#\s*!.*ruby/o
|
74
|
-
ftmp = Tempfile::new("#{ $$ }_#{ File::basename(f) }")
|
75
|
-
begin
|
76
|
-
fd.rewind
|
77
|
-
ftmp.puts "#!#{ $ruby }"
|
78
|
-
while((buf = fd.read(8192)))
|
79
|
-
ftmp.write buf
|
80
|
-
end
|
81
|
-
ftmp.close
|
82
|
-
yield ftmp.path
|
83
|
-
ensure
|
84
|
-
ftmp.close!
|
85
|
-
end
|
86
|
-
else
|
87
|
-
yield f
|
88
|
-
end
|
89
|
-
end
|
90
|
-
#}}}
|
91
|
-
end
|
92
|
-
def ARGV.switch
|
93
|
-
#{{{
|
94
|
-
return nil if self.empty?
|
95
|
-
arg = self.shift
|
96
|
-
return nil if arg == '--'
|
97
|
-
if arg =~ /^-(.)(.*)/
|
98
|
-
return arg if $1 == '-'
|
99
|
-
raise 'unknown switch "-"' if $2.index('-')
|
100
|
-
self.unshift "-#{$2}" if $2.size > 0
|
101
|
-
"-#{$1}"
|
102
|
-
else
|
103
|
-
self.unshift arg
|
104
|
-
nil
|
105
|
-
end
|
106
|
-
#}}}
|
107
|
-
end
|
108
|
-
def ARGV.req_arg
|
109
|
-
#{{{
|
110
|
-
self.shift || raise('missing argument')
|
111
|
-
#}}}
|
112
|
-
end
|
113
|
-
def linkify d, linked = []
|
114
|
-
#--{{{
|
115
|
-
if test ?d, d
|
116
|
-
versioned = Dir[ File::join(d, "*-[0-9].[0-9].[0-9].rb") ]
|
117
|
-
versioned.each do |v|
|
118
|
-
src, dst = v, v.gsub(%r/\-[\d\.]+\.rb$/, '.rb')
|
119
|
-
lnk = nil
|
120
|
-
begin
|
121
|
-
if test ?l, dst
|
122
|
-
lnk = "#{ dst }.lnk"
|
123
|
-
puts "#{ dst } -> #{ lnk }"
|
124
|
-
File::rename dst, lnk
|
125
|
-
end
|
126
|
-
unless test ?e, dst
|
127
|
-
puts "#{ src } -> #{ dst }"
|
128
|
-
File::copy src, dst
|
129
|
-
linked << dst
|
130
|
-
end
|
131
|
-
ensure
|
132
|
-
if lnk
|
133
|
-
at_exit do
|
134
|
-
puts "#{ lnk } -> #{ dst }"
|
135
|
-
File::rename lnk, dst
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
linked
|
142
|
-
#--}}}
|
143
|
-
end
|
144
|
-
|
145
|
-
|
146
|
-
#
|
147
|
-
# main program
|
148
|
-
#
|
149
|
-
|
150
|
-
libdir = $site_libdir
|
151
|
-
bindir = $bindir
|
152
|
-
no_linkify = false
|
153
|
-
linked = nil
|
154
|
-
help = false
|
155
|
-
|
156
|
-
usage = <<-usage
|
157
|
-
#{ File::basename $0 }
|
158
|
-
-d, --destdir <destdir>
|
159
|
-
-l, --libdir <libdir>
|
160
|
-
-b, --bindir <bindir>
|
161
|
-
-r, --ruby <ruby>
|
162
|
-
-n, --no_linkify
|
163
|
-
-s, --sudo
|
164
|
-
-h, --help
|
165
|
-
usage
|
166
|
-
|
167
|
-
begin
|
168
|
-
while switch = ARGV.switch
|
169
|
-
case switch
|
170
|
-
when '-d', '--destdir'
|
171
|
-
libdir = ARGV.req_arg
|
172
|
-
when '-l', '--libdir'
|
173
|
-
libdir = ARGV.req_arg
|
174
|
-
when '-b', '--bindir'
|
175
|
-
bindir = ARGV.req_arg
|
176
|
-
when '-r', '--ruby'
|
177
|
-
$ruby = ARGV.req_arg
|
178
|
-
when '-n', '--no_linkify'
|
179
|
-
no_linkify = true
|
180
|
-
when '-s', '--sudo'
|
181
|
-
sudo = 'sudo'
|
182
|
-
when '-h', '--help'
|
183
|
-
help = true
|
184
|
-
else
|
185
|
-
raise "unknown switch #{switch.dump}"
|
186
|
-
end
|
187
|
-
end
|
188
|
-
rescue
|
189
|
-
STDERR.puts $!.to_s
|
190
|
-
STDERR.puts usage
|
191
|
-
exit 1
|
192
|
-
end
|
193
|
-
|
194
|
-
if help
|
195
|
-
STDOUT.puts usage
|
196
|
-
exit
|
197
|
-
end
|
198
|
-
|
199
|
-
system "#{ sudo } #{ $ruby } pre-install.rb" if test(?s, 'pre-install.rb')
|
200
|
-
|
201
|
-
unless no_linkify
|
202
|
-
linked = linkify('lib') + linkify('bin')
|
203
|
-
end
|
204
|
-
|
205
|
-
system "#{ $ruby } extconf.rb && make && #{ sudo } make install" if test(?s, 'extconf.rb')
|
206
|
-
|
207
|
-
install_rb(LIBDIR, libdir, LIBDIR_MODE)
|
208
|
-
install_rb(BINDIR, bindir, BINDIR_MODE, bin=true)
|
209
|
-
|
210
|
-
if linked
|
211
|
-
linked.each{|path| File::rm_f path}
|
212
|
-
end
|
213
|
-
|
214
|
-
system "#{ sudo } #{ $ruby } post-install.rb" if test(?s, 'post-install.rb')
|