pmap 1.0.2 → 1.1.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
  SHA1:
3
- metadata.gz: 18142e8b4288995523855dca836e2e5a68626842
4
- data.tar.gz: 1c434f5d568b3b3c49443f0297034fb53d8daaa2
3
+ metadata.gz: 0eeba30c0921e39d013d4a2cd58c00ecd1c50e69
4
+ data.tar.gz: 5422d1dabc31a8fb65329bc35a2dd671ccf8a24e
5
5
  SHA512:
6
- metadata.gz: 3ff6f9af2481e06d4c909549fcfba4ebbff7dfefbbfbac7ec9526970173a589c9bb072b602d27466dae7b644571affb8114f3a2e66c81cda67ab994d7b59ab25
7
- data.tar.gz: 8f15a3213ea2ebacc0392e584db12444fa95696b60a955d579ccb36961a4f4f4ccf9a4c497b5a00b7635bd946bf96997ace6902f987f33021cbbd60daa73143b
6
+ metadata.gz: d7321a043d56bd25f3c14b8219226c4381ccc96d5c5605708205a9b8acb56b019c5b80425ba6631272677496ef78a5525e2c1c7a8134a5424a0c050ea55bab55
7
+ data.tar.gz: 8f189ffaf99cf4f3d7cc7b7e97c204d63375714073559f0cbf2861e55e32e63fdfa9457bc0c79302f323ee307aa9e783100e4f5f6f945007abd2952974db3184
@@ -5,10 +5,11 @@ rvm:
5
5
  - 1.9.2
6
6
  - 1.9.3
7
7
  - 2.0.0
8
- - 2.1.3
9
- - 2.2.0-preview1
8
+ - 2.1.6
9
+ - 2.2.2
10
10
  - jruby-18mode
11
11
  - jruby-19mode
12
+ - jruby-9.0.0.0
12
13
  - jruby-head
13
14
  - rbx-2
14
15
  - ree
@@ -16,4 +17,5 @@ rvm:
16
17
  matrix:
17
18
  allow_failures:
18
19
  - rvm: jruby-head
20
+ - rvm: rbx-2
19
21
  - rvm: ruby-head
@@ -1,32 +1,50 @@
1
1
  # Contributor Code of Conduct
2
2
 
3
- As contributors and maintainers of this project, we pledge to respect
4
- all people who contribute through reporting issues, posting feature
5
- requests, updating documentation, submitting pull requests or patches,
6
- and other activities.
7
-
8
- We are committed to making participation in this project a
9
- harassment-free experience for everyone, regardless of level of
10
- experience, gender, gender identity and expression, sexual
11
- orientation, disability, personal appearance, body size, race, age, or
12
- religion.
13
-
14
- Examples of unacceptable behavior by participants include the use of
15
- sexual language or imagery, derogatory comments or personal attacks,
16
- trolling, public or private harassment, insults, or other
17
- unprofessional conduct.
18
-
19
- Project maintainers have the right and responsibility to remove, edit,
20
- or reject comments, commits, code, wiki edits, issues, and other
21
- contributions that are not aligned to this Code of Conduct. Project
22
- maintainers who do not follow the Code of Conduct may be removed from
23
- the project team.
24
-
25
- Instances of abusive, harassing, or otherwise unacceptable behavior
26
- may be reported by opening an issue or contacting one or more of the
27
- project maintainers.
28
-
29
- This Code of Conduct is adapted from the
30
- [Contributor Covenant](http://contributor-covenant.org),
31
- version 1.0.0, available at
32
- [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all people who
5
+ contribute through reporting issues, posting feature requests, updating
6
+ documentation, submitting pull requests or patches, and other activities.
7
+
8
+ We are committed to making participation in this project a harassment-free
9
+ experience for everyone, regardless of level of experience, gender, gender
10
+ identity and expression, sexual orientation, disability, personal appearance,
11
+ body size, race, ethnicity, age, religion, or nationality.
12
+
13
+ Examples of unacceptable behavior by participants include:
14
+
15
+ * The use of sexualized language or imagery
16
+ * Personal attacks
17
+ * Trolling or insulting/derogatory comments
18
+ * Public or private harassment
19
+ * Publishing other's private information, such as physical or electronic
20
+ addresses, without explicit permission
21
+ * Other unethical or unprofessional conduct
22
+
23
+ Project maintainers have the right and responsibility to remove, edit, or
24
+ reject comments, commits, code, wiki edits, issues, and other contributions
25
+ that are not aligned to this Code of Conduct, or to ban temporarily or
26
+ permanently any contributor for other behaviors that they deem inappropriate,
27
+ threatening, offensive, or harmful.
28
+
29
+ By adopting this Code of Conduct, project maintainers commit themselves to
30
+ fairly and consistently applying these principles to every aspect of managing
31
+ this project. Project maintainers who do not follow or enforce the Code of
32
+ Conduct may be permanently removed from the project team.
33
+
34
+ This code of conduct applies both within project spaces and in public spaces
35
+ when an individual is representing the project or its community.
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
38
+ reported by contacting a project maintainer at bruce.adams@acm.org. All
39
+ complaints will be reviewed and investigated and will result in a response that
40
+ is deemed necessary and appropriate to the circumstances. Maintainers are
41
+ obligated to maintain confidentiality with regard to the reporter of an
42
+ incident.
43
+
44
+
45
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
46
+ version 1.3.0, available at
47
+ [http://contributor-covenant.org/version/1/3/0/][version]
48
+
49
+ [homepage]: http://contributor-covenant.org
50
+ [version]: http://contributor-covenant.org/version/1/3/0/
data/README.md CHANGED
@@ -1,11 +1,12 @@
1
1
  pmap [![Build Status](https://secure.travis-ci.org/bruceadams/pmap.png)](http://travis-ci.org/bruceadams/pmap) [![Code Climate](https://codeclimate.com/github/bruceadams/pmap.png)](https://codeclimate.com/github/bruceadams/pmap)
2
2
  ====
3
3
 
4
- This Ruby gem adds two methods to any Enumerable (notably including
4
+ This Ruby gem adds three methods to any Enumerable (notably including
5
5
  any Array). The two added methods are:
6
6
 
7
7
  * _pmap_ parallel map
8
8
  * _peach_ parallel each
9
+ * _peach_with_index_ parallel each_with_index
9
10
 
10
11
  Threading in Ruby has limitations.
11
12
  ----------------------------------
@@ -32,11 +33,6 @@ Ruby threads means the requests will be issued very quickly, well
32
33
  before the responses start coming back. As responses come back, they
33
34
  will be processed as they arrive.
34
35
 
35
- Thread Count
36
- ----------------
37
-
38
- The thread count defaults to 64 and is set based on `$pmap_default_thread_count`.
39
-
40
36
  Example
41
37
  -------
42
38
 
@@ -54,3 +50,19 @@ get_quote ranges averages 0.5 seconds.
54
50
  # This will take about half a second;
55
51
  # however long the single slowest response took.
56
52
  stock_quotes = stock_symbols.pmap {|s| get_quote(s)}
53
+
54
+ Thread Count
55
+ ------------
56
+
57
+ The thread count defaults to 64 and is set based on `$pmap_default_thread_count`.
58
+
59
+ You can also set the thread count per call by passing it as an argument to the `pmap` and `peach` methods.
60
+
61
+ # Use the default thread count (64)
62
+ (1..128).peach { |i| sleep 1 } # Takes 2 seconds
63
+
64
+ # Use a thread count of 128
65
+ (1..128).peach(128) { |i| sleep 1 } # Takes 1 second
66
+
67
+ # Use a thread count of 2
68
+ (1..128).peach(2) { |i| sleep 1 } # Takes 64 seconds
@@ -1,58 +1,54 @@
1
1
  require 'thread' unless defined?(Mutex)
2
+ require "pmap/thread_pool"
2
3
 
3
4
  # Global variable for the default thread pool size.
4
5
  $pmap_default_thread_count ||= 64
5
6
 
6
7
  module PMap
7
- class DummyOutput
8
- def []=(idx, val)
9
- end
10
- end
11
-
12
8
  def self.included(base)
13
9
  base.class_eval do
14
- # Parallel "map" for any Enumerable.
10
+
11
+ # Public: Parallel "map" for any Enumerable.
12
+ #
13
+ # thread_count - maximum number of threads to create (optional)
14
+ #
15
15
  # Requires a block of code to run for each Enumerable item.
16
- # [thread_count] is number of threads to create. Optional.
16
+ #
17
17
  def pmap(thread_count=nil, &proc)
18
- in_array = self.to_a # I'm not sure how expensive this is...
19
- out_array = Array.new(in_array.size)
20
- process_core(thread_count, in_array, out_array, &proc)
21
- out_array
22
- end
23
-
24
- def process_core(thread_count, in_array, out_array, &proc)
25
- thread_count = thread_count(thread_count, in_array)
26
- size = in_array.size
27
-
28
- semaphore = Mutex.new
29
- index = -1 # Our use of index is protected by semaphore
30
-
31
- threads = (0...thread_count).map {
32
- Thread.new {
33
- i = nil
34
- while (semaphore.synchronize {i = (index += 1)}; i < size)
35
- out_array[i] = yield(in_array[i])
36
- end
37
- }
38
- }
39
- threads.each {|t| t.join}
18
+ Array.new.tap do |result|
19
+ peach_with_index(thread_count) do |item, index|
20
+ result[index] = proc.call(item)
21
+ end
22
+ end
40
23
  end
41
- private :process_core
42
24
 
43
- def thread_count(user_requested_count, items)
44
- user_requested_count ||= $pmap_default_thread_count
45
- raise ArgumentError, "thread_count must be at least one." unless
46
- user_requested_count.respond_to?(:>=) && user_requested_count >= 1
47
- [user_requested_count, items.size].min
25
+ # Public: Parallel "each" for any Enumerable.
26
+ #
27
+ # thread_count - maximum number of threads to create (optional)
28
+ #
29
+ # Requires a block of code to run for each Enumerable item.
30
+ #
31
+ def peach(thread_count=nil, &proc)
32
+ peach_with_index(thread_count) do |item, index|
33
+ proc.call(item)
34
+ end
35
+ self
48
36
  end
49
- private :thread_count
50
37
 
51
- # Parallel "each" for any Enumerable.
38
+ # Public: Parallel each_with_index for any Enumerable
39
+ #
40
+ # thread_count - maximum number of threads to create (optional)
41
+ #
52
42
  # Requires a block of code to run for each Enumerable item.
53
- # [thread_count] is number of threads to create. Optional.
54
- def peach(thread_count=nil, &proc)
55
- process_core(thread_count, self.to_a, DummyOutput.new, &proc)
43
+ #
44
+ def peach_with_index(thread_count=nil, &proc)
45
+ thread_count ||= $pmap_default_thread_count
46
+ pool = ThreadPool.new(thread_count)
47
+
48
+ each_with_index do |item, index|
49
+ pool.schedule(item, index, &proc)
50
+ end
51
+ pool.shutdown
56
52
  self
57
53
  end
58
54
  end
@@ -0,0 +1,65 @@
1
+ # Internal: A thread pool for managing the threads used by the pmap functions
2
+ #
3
+ # Example:
4
+ #
5
+ # pool = PMap::ThreadPool.new(16)
6
+ # array.each do |item|
7
+ # pool.schedule do
8
+ # item.some_io_intense_operation
9
+ # end
10
+ # end
11
+ #
12
+ # pool.shutdown
13
+ #
14
+ module PMap
15
+ class ThreadPool
16
+
17
+ # Public: Initializes a new thread pool
18
+ #
19
+ # max - the maximum number of threads to spawn
20
+ #
21
+ def initialize(max)
22
+ raise ArgumentError, "max must be at least one." unless
23
+ max.respond_to?(:>=) && max >= 1
24
+
25
+ @max = max
26
+ @jobs = Queue.new
27
+ @workers = []
28
+ end
29
+
30
+ # Public: Schedules a new job to run in a thread
31
+ #
32
+ # *args - any arguments that will be passed to the block
33
+ # &job - the block that will be executed on the thread
34
+ #
35
+ def schedule(*args, &job)
36
+ @jobs << [job, args]
37
+ spawn_worker if @workers.size < @max
38
+ end
39
+
40
+ # Public: Shuts down the thread pool and waits for any running threads to
41
+ # complete
42
+ #
43
+ def shutdown
44
+ @workers.size.times do
45
+ @jobs << :stop_working
46
+ end
47
+ @workers.each(&:join)
48
+ end
49
+
50
+ private
51
+
52
+ # Private: Spawns a new thread to work on the scheduled jobs
53
+ #
54
+ def spawn_worker
55
+ thread = Thread.new do
56
+ while (command = @jobs.pop) != :stop_working
57
+ job, args = command
58
+ job.call(*args)
59
+ end
60
+ end
61
+
62
+ @workers << thread
63
+ end
64
+ end
65
+ end
@@ -1,3 +1,3 @@
1
1
  module Pmap
2
- VERSION = "1.0.2"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -6,8 +6,9 @@ Gem::Specification.new do |s|
6
6
  s.name = 'pmap'
7
7
  s.version = Pmap::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
- s.authors = ['Bruce Adams', 'Jake Goulding']
10
- s.email = ['bruce.adams@acm.org', 'jake.goulding@gmail.com']
9
+ s.license = 'Apache-2.0'
10
+ s.authors = ['Bruce Adams', 'Jake Goulding', 'David Biehl']
11
+ s.email = ['bruce.adams@acm.org', 'jake.goulding@gmail.com', 'me@davidbiehl.com']
11
12
  s.homepage = 'https://github.com/bruceadams/pmap'
12
13
  s.summary = %q{Add parallel methods into Enumerable: pmap and peach}
13
14
  s.description = %q{Add parallel methods into Enumerable: pmap and peach}
@@ -60,4 +60,15 @@ class Pmap_Test < Test::Unit::TestCase
60
60
  assert(elapsed >= 2, 'Limited threads too fast: %.1f seconds' % elapsed)
61
61
  assert(elapsed < 3, 'Parallel sleeps too slow: %.1f seconds' % elapsed)
62
62
  end
63
+
64
+ def test_peach_with_index
65
+ subject = ["a", "b", "c"]
66
+ output = []
67
+
68
+ subject.peach_with_index do |letter, index|
69
+ output << [letter, index]
70
+ end
71
+
72
+ assert_equal([["a", 0], ["b", 1], ["c", 2]].sort, output.sort)
73
+ end
63
74
  end
metadata CHANGED
@@ -1,15 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pmap
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bruce Adams
8
8
  - Jake Goulding
9
+ - David Biehl
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2014-12-14 00:00:00.000000000 Z
13
+ date: 2015-11-08 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: test-unit
@@ -29,6 +30,7 @@ description: 'Add parallel methods into Enumerable: pmap and peach'
29
30
  email:
30
31
  - bruce.adams@acm.org
31
32
  - jake.goulding@gmail.com
33
+ - me@davidbiehl.com
32
34
  executables: []
33
35
  extensions: []
34
36
  extra_rdoc_files: []
@@ -41,11 +43,13 @@ files:
41
43
  - README.md
42
44
  - Rakefile
43
45
  - lib/pmap.rb
46
+ - lib/pmap/thread_pool.rb
44
47
  - lib/pmap/version.rb
45
48
  - pmap.gemspec
46
49
  - test/pmap_test.rb
47
50
  homepage: https://github.com/bruceadams/pmap
48
- licenses: []
51
+ licenses:
52
+ - Apache-2.0
49
53
  metadata: {}
50
54
  post_install_message:
51
55
  rdoc_options: []
@@ -63,8 +67,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
63
67
  version: '0'
64
68
  requirements: []
65
69
  rubyforge_project:
66
- rubygems_version: 2.2.2
70
+ rubygems_version: 2.4.1
67
71
  signing_key:
68
72
  specification_version: 4
69
73
  summary: 'Add parallel methods into Enumerable: pmap and peach'
70
- test_files: []
74
+ test_files:
75
+ - test/pmap_test.rb