jobQueue 1.0.1
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.
- data/LICENSE +27 -0
- data/README.rdoc +85 -0
- data/bin/prun.rb +19 -0
- data/gemspec +19 -0
- data/lib/jobqueue.rb +83 -0
- metadata +52 -0
data/LICENSE
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
Copyright (c) 2011, Ralf Mueller (stark.dreamdetective@googlemail.com)
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
* Redistributions of source code must retain the above copyright notice,
|
8
|
+
this list of conditions and the following disclaimer.
|
9
|
+
|
10
|
+
* Redistributions in binary form must reproduce the above copyright
|
11
|
+
notice, this list of conditions and the following disclaimer in the
|
12
|
+
documentation and/or other materials provided with the distribution.
|
13
|
+
|
14
|
+
* The names of its contributors may not be used to endorse or promote
|
15
|
+
products derived from this software without specific prior written
|
16
|
+
permission.
|
17
|
+
|
18
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
19
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
20
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
21
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
22
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
23
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
24
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
25
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
26
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
27
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
= JobQueue - Let run your jobs in parallel
|
2
|
+
|
3
|
+
This package contains jobQueue:
|
4
|
+
* A simple class to parallalize your work on a user definend number of threads
|
5
|
+
* A ruby script, which uses the above class to run each line of a shell script
|
6
|
+
|
7
|
+
jobQueue can do the following things:
|
8
|
+
|
9
|
+
* Run shell commands
|
10
|
+
* Run instance and class methods
|
11
|
+
* Run Procs and Lambdas
|
12
|
+
* Respect user definded locks
|
13
|
+
|
14
|
+
== Installation
|
15
|
+
|
16
|
+
=== Gem Installation
|
17
|
+
|
18
|
+
Download and install jobQueue with the following.
|
19
|
+
|
20
|
+
gem install jobQueue
|
21
|
+
|
22
|
+
=== Requirements
|
23
|
+
|
24
|
+
JobQueue requires Ruby only, but versions 1.9.x are needed to make use of system threads.
|
25
|
+
|
26
|
+
== Usage
|
27
|
+
|
28
|
+
=== Parallelize Ruby's procs, lambdas and things
|
29
|
+
|
30
|
+
Create a JobQueue with nThreads worker with:
|
31
|
+
|
32
|
+
jq = JobQueue.new(nThreads)
|
33
|
+
|
34
|
+
Use its push method to put in something to do
|
35
|
+
|
36
|
+
* For procs and lambdas:
|
37
|
+
|
38
|
+
jp.push(myProc,arg0,arg1,...)
|
39
|
+
|
40
|
+
* For object methods:
|
41
|
+
|
42
|
+
jq.push([myObject,[:method,arg0,arg1,...])
|
43
|
+
|
44
|
+
* Same code can be used for class methods:
|
45
|
+
|
46
|
+
jq.push(myClass,[:myClassMethod,arg0,arg1,...])
|
47
|
+
|
48
|
+
To start the workers, call
|
49
|
+
|
50
|
+
jq.run
|
51
|
+
|
52
|
+
That's it. You might have look at tests, that come with the jobQueue gem.
|
53
|
+
|
54
|
+
=== Parallelize system commands
|
55
|
+
|
56
|
+
Any string is expected to be a valid system command and executed via Ruby's system call, e.g.
|
57
|
+
|
58
|
+
jq.push('find ./src -name "*.rb"','find ./downloads -name "*.rb"')
|
59
|
+
|
60
|
+
will start 2 parallel searches for ruby files.
|
61
|
+
|
62
|
+
== Support, Issues, Bugs, ...
|
63
|
+
|
64
|
+
As long there is no dedicataed project page, please use direct mail or the ruby-lang mailing list.
|
65
|
+
|
66
|
+
== Credits
|
67
|
+
|
68
|
+
[<b>Robert Klemme</b>] For the first hints: https://www.ruby-forum.com/topic/68001#86298
|
69
|
+
|
70
|
+
== License
|
71
|
+
|
72
|
+
jobQueue makes use of the BSD License
|
73
|
+
|
74
|
+
:include: LICENSE
|
75
|
+
|
76
|
+
|
77
|
+
---
|
78
|
+
|
79
|
+
= Other stuff
|
80
|
+
|
81
|
+
Author:: Ralf Mueller <stark.dreamdetective@gmail.com>
|
82
|
+
Requires:: Ruby 1.9 or later
|
83
|
+
License:: Copyright 2011 by Ralf Mueller
|
84
|
+
Released under BSD-style license. See the LICENSE
|
85
|
+
file included in the distribution.
|
data/bin/prun.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'jobqueue'
|
3
|
+
# ==============================================================================
|
4
|
+
# Example script:
|
5
|
+
# Read in a script and process line in parallel with a given number of threads:
|
6
|
+
# Usage: prun.rb 10 myScript.sh
|
7
|
+
# Attention: each line of the input script is regarded as a separate command
|
8
|
+
# ==============================================================================
|
9
|
+
unless ARGV.size == 2
|
10
|
+
warn "provide number of threads and input data"
|
11
|
+
exit
|
12
|
+
end
|
13
|
+
# read number of threads
|
14
|
+
noTh = ARGV[0].to_i
|
15
|
+
# read file line per line
|
16
|
+
lines = File.open(ARGV[1]).readlines.map(&:chomp)
|
17
|
+
q = JobQueue.new(noTh)
|
18
|
+
q.push(*lines)
|
19
|
+
q.run
|
data/gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
spec = Gem::Specification.new do |s|
|
4
|
+
s.name = "jobQueue"
|
5
|
+
s.version = '1.0.1'
|
6
|
+
s.platform = Gem::Platform::RUBY
|
7
|
+
s.bindir = 'bin'
|
8
|
+
s.files = ["lib/jobqueue.rb","bin/prun.rb"] + ["gemspec","LICENSE","README.rdoc"]
|
9
|
+
s.executables << 'prun.rb'
|
10
|
+
s.description = "Run Shell commands or Ruby methods in parallel"
|
11
|
+
s.summary = s.description
|
12
|
+
s.author = "Ralf Mueller"
|
13
|
+
s.email = "stark.dreamdetective@gmail.com"
|
14
|
+
# s.homepage = "http://
|
15
|
+
s.extra_rdoc_files = ["README.rdoc","LICENSE"]
|
16
|
+
s.required_ruby_version = ">= 1.9"
|
17
|
+
end
|
18
|
+
|
19
|
+
# vim:ft=ruby
|
data/lib/jobqueue.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'thread'
|
3
|
+
require 'pp'
|
4
|
+
# ==============================================================================
|
5
|
+
# Author: Ralf Mueller, ralf.mueller@zmaw.de
|
6
|
+
# suggestions from Robert Klemme (https://www.ruby-forum.com/topic/68001#86298)
|
7
|
+
#
|
8
|
+
# ==============================================================================
|
9
|
+
# Sized Queue for limiting the number of parallel jobs
|
10
|
+
# ==============================================================================
|
11
|
+
class JobQueue
|
12
|
+
attr_reader :size, :queue, :threads
|
13
|
+
|
14
|
+
# Create a new queue qith a given number of worker threads
|
15
|
+
def initialize(size)
|
16
|
+
@size = size
|
17
|
+
@queue = Queue.new
|
18
|
+
end
|
19
|
+
|
20
|
+
# Put jobs into the queue. Use
|
21
|
+
# strings for system commands
|
22
|
+
# proc,args for single methods
|
23
|
+
# [object,[:methods,args]] for sende messages to objects
|
24
|
+
#
|
25
|
+
def push(*items)
|
26
|
+
items.each {|it| @queue << it}
|
27
|
+
end
|
28
|
+
|
29
|
+
# Start workers to run through the queue
|
30
|
+
def run
|
31
|
+
@threads = (1..@size).map {|i|
|
32
|
+
Thread.new(@queue) {|q|
|
33
|
+
until ( q == ( task = q.deq ) )
|
34
|
+
if task.kind_of? String
|
35
|
+
system(task)
|
36
|
+
elsif task.kind_of? Proc
|
37
|
+
task.call
|
38
|
+
elsif task.kind_of? Array
|
39
|
+
if task.size > 1
|
40
|
+
if not task[1].kind_of? Array
|
41
|
+
# Expects proc/lambda with arguments, e.g. [mysqrt,2.789]
|
42
|
+
task[0].call(*task[1..-1])
|
43
|
+
else
|
44
|
+
# expect an object in task[0] and one of its methods with arguments in task[1] as a symbol
|
45
|
+
# e.g. [a,[:attribute=,1]
|
46
|
+
task[0].send(task[1][0],*task[1][1..-1])
|
47
|
+
end
|
48
|
+
else
|
49
|
+
warn 'provide 2d arrays'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
}
|
54
|
+
}
|
55
|
+
@threads.size.times { @queue.enq @queue}
|
56
|
+
@threads.each {|t| t.join}
|
57
|
+
end
|
58
|
+
|
59
|
+
# Get the maximum number of parallel runs
|
60
|
+
def number_of_processors
|
61
|
+
if RUBY_PLATFORM =~ /linux/
|
62
|
+
return `cat /proc/cpuinfo | grep processor | wc -l`.to_i
|
63
|
+
elsif RUBY_PLATFORM =~ /darwin/
|
64
|
+
return `sysctl -n hw.logicalcpu`.to_i
|
65
|
+
elsif RUBY_PLATFORM =~ /(win32|mingw|cygwin)/
|
66
|
+
# this works for windows 2000 or greater
|
67
|
+
require 'win32ole'
|
68
|
+
wmi = WIN32OLE.connect("winmgmts://")
|
69
|
+
wmi.ExecQuery("select * from Win32_ComputerSystem").each do |system|
|
70
|
+
begin
|
71
|
+
processors = system.NumberOfLogicalProcessors
|
72
|
+
rescue
|
73
|
+
processors = 0
|
74
|
+
end
|
75
|
+
return [system.NumberOfProcessors, processors].max
|
76
|
+
end
|
77
|
+
elseif RUBY_PLATFORM =~ /java/
|
78
|
+
return Runtime.getRuntime().availableProcessors().to_i
|
79
|
+
end
|
80
|
+
raise "can't determine 'number_of_processors' for '#{RUBY_PLATFORM}'"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
metadata
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jobQueue
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ralf Mueller
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-12-12 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Run Shell commands or Ruby methods in parallel
|
15
|
+
email: stark.dreamdetective@gmail.com
|
16
|
+
executables:
|
17
|
+
- prun.rb
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files:
|
20
|
+
- README.rdoc
|
21
|
+
- LICENSE
|
22
|
+
files:
|
23
|
+
- lib/jobqueue.rb
|
24
|
+
- bin/prun.rb
|
25
|
+
- gemspec
|
26
|
+
- LICENSE
|
27
|
+
- README.rdoc
|
28
|
+
homepage:
|
29
|
+
licenses: []
|
30
|
+
post_install_message:
|
31
|
+
rdoc_options: []
|
32
|
+
require_paths:
|
33
|
+
- lib
|
34
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
35
|
+
none: false
|
36
|
+
requirements:
|
37
|
+
- - ! '>='
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.9'
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
requirements: []
|
47
|
+
rubyforge_project:
|
48
|
+
rubygems_version: 1.8.11
|
49
|
+
signing_key:
|
50
|
+
specification_version: 3
|
51
|
+
summary: Run Shell commands or Ruby methods in parallel
|
52
|
+
test_files: []
|