celluloid-pmap 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.travis.yml +3 -3
- data/README.md +42 -14
- data/celluloid-pmap.gemspec +3 -2
- data/lib/celluloid/pmap.rb +7 -3
- data/lib/celluloid/pmap/parallel_map_worker.rb +2 -2
- data/lib/celluloid/pmap/version.rb +1 -1
- data/spec/celluloid/pmap/parallel_map_worker_spec.rb +2 -2
- data/spec/celluloid/pmap_spec.rb +7 -0
- data/spec/support/benchmark_spec.rb +5 -3
- metadata +33 -33
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: dd8a1f6f0315f3acd623701b984e804bb3f1d282
|
4
|
+
data.tar.gz: b352db781fc66bedf019e7e70eca037731a382fe
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5221c5887556d0530b0a8c3f5bf13f9f5c17d49fd8a970899d19eff295d62a73f8978d7c64829e6b29638597869a30e198c6e5bd891c25b3b191ac2b684c230e
|
7
|
+
data.tar.gz: 30c8b6a0c707ebb2f1f919d2146c6a1b3095055b513ea283f0de7bf873f483325e294486cc563bfcfb996ab4c28b03251338d040c81d6c1dcb80be81173ae991
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Celluloid::Pmap
|
2
2
|
|
3
|
-
[![Build Status](https://travis-ci.org/jwo/celluloid-pmap.png?branch=master)](https://travis-ci.org/jwo/celluloid-pmap)
|
3
|
+
[![Build Status](https://travis-ci.org/jwo/celluloid-pmap.png?branch=master)](https://travis-ci.org/jwo/celluloid-pmap)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/jwo/celluloid-pmap.png)](https://codeclimate.com/github/jwo/celluloid-pmap)
|
4
5
|
|
5
6
|
Parallel Mapping using Celluloid
|
6
7
|
|
@@ -17,6 +18,19 @@ The pmap will return an array of values when all of the Futures have completed a
|
|
17
18
|
|
18
19
|
The pool can help to make sure you don't exceed your connection resources. A common use case for this is in Rails, you can easily exceed the default ActiveRecord connection size.
|
19
20
|
|
21
|
+
### Use with ActiveRecord
|
22
|
+
|
23
|
+
Some users have reported connection leaking with using ActiveRecord objects in a
|
24
|
+
pmap. You can reuse a connection with this code below. You can read the backstory
|
25
|
+
on the [decision to not include an AR dependency](https://github.com/jwo/celluloid-pmap/pull/2).
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
users.pmap(4) do |user|
|
29
|
+
ActiveRecord::Base.connection_pool.with_connection { user.do_hefty_stuff! }
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
|
20
34
|
### Inspiration for this code
|
21
35
|
|
22
36
|
Tony Arcieri created [celluloid](http://celluloid.io/), and the [simple_pmap example](https://github.com/celluloid/celluloid/blob/master/examples/simple_pmap.rb) from which this codebase started
|
@@ -31,11 +45,11 @@ Because I've been implementing the same initializer code in every project I've w
|
|
31
45
|
|
32
46
|
### What rubies will this run on?
|
33
47
|
|
34
|
-
*
|
35
|
-
*
|
48
|
+
* 2.0.0
|
49
|
+
* 2.1.3
|
50
|
+
* 2.2.0
|
36
51
|
* jruby-19mode
|
37
52
|
* jruby-head
|
38
|
-
* rbx-19mode
|
39
53
|
|
40
54
|
|
41
55
|
## Installation
|
@@ -52,16 +66,20 @@ Default usage will execute in parallel. Simply pass a block to an Enumerable
|
|
52
66
|
```
|
53
67
|
puts "You'll see the puts happen instantly, and the sleep in parallel"
|
54
68
|
|
55
|
-
[55,65,75,85].pmap{|
|
56
|
-
|
69
|
+
[55,65,75,85].pmap{|limit| puts "I can't drive #{limit}!"; sleep(rand)}
|
70
|
+
```
|
71
|
+
|
72
|
+
Or something more real-world?
|
57
73
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
74
|
+
```
|
75
|
+
User.active.all.pmap do |user|
|
76
|
+
stripe_user = Stripe::Customer.retrieve user.stripe_customer_token
|
77
|
+
user.invoices = BuildsInvoicesFromStripeUser.build(stripe_user)
|
78
|
+
user.save
|
79
|
+
end
|
62
80
|
```
|
63
81
|
|
64
|
-
Problem: When using with ActiveRecord, you can quickly run out of connections.
|
82
|
+
Problem: When using with ActiveRecord, you can quickly run out of connections.
|
65
83
|
Answer: Specify the max number of threads (actors) to create at once!
|
66
84
|
|
67
85
|
```
|
@@ -76,15 +94,21 @@ puts [1,2,3].pmap(2){|speed_limit| puts Time.now.tap { sleep(3) }}
|
|
76
94
|
|
77
95
|
We default pmap's threads to the number of Celluloid cores in the system.
|
78
96
|
|
79
|
-
|
97
|
+
### When should you use pmap over Sidekiq or Actors?
|
98
|
+
|
99
|
+
When you need the response right away. (well, right away in the workflow sense). This is crazy good in IRB too. Destroying multiple records in parallel is nice.
|
100
|
+
|
101
|
+
### When will this help performance?
|
80
102
|
|
81
103
|
* When the blocks are IO bound (like database or web queries)
|
82
104
|
* When you're running JRuby or Rubinius
|
83
105
|
* When you're running C Extensions
|
84
106
|
|
85
|
-
|
107
|
+
### So what will this not speed things up?
|
86
108
|
|
87
|
-
* Pure math or ruby computations
|
109
|
+
* Pure math or ruby computations*
|
110
|
+
|
111
|
+
\*except if you're on JRuby or Rubinius, where this will still speed those along quite nicely.
|
88
112
|
|
89
113
|
## Image Credit
|
90
114
|
|
@@ -94,6 +118,10 @@ Universe," AND "She-Ra: Princess of Power" are copyright Mattel.
|
|
94
118
|
|
95
119
|
More information on He-Man can be found at the unspeakably wow site: http://castlegrayskull.org
|
96
120
|
|
121
|
+
## Contributors
|
122
|
+
|
123
|
+
* [Jason Voegele](https://github.com/jvoegele)
|
124
|
+
|
97
125
|
## Contributing
|
98
126
|
|
99
127
|
1. Fork it
|
data/celluloid-pmap.gemspec
CHANGED
@@ -18,8 +18,9 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
19
|
gem.require_paths = ["lib"]
|
20
20
|
|
21
|
-
gem.add_dependency('celluloid', '~> 0.
|
21
|
+
gem.add_dependency('celluloid', '~> 0.16')
|
22
22
|
|
23
23
|
gem.add_development_dependency "rake"
|
24
|
-
gem.add_development_dependency "rspec"
|
24
|
+
gem.add_development_dependency "rspec", "2.99"
|
25
|
+
gem.add_development_dependency "pry"
|
25
26
|
end
|
data/lib/celluloid/pmap.rb
CHANGED
@@ -8,9 +8,13 @@ module Celluloid
|
|
8
8
|
def self.included(base)
|
9
9
|
base.class_eval do
|
10
10
|
|
11
|
-
def pmap(
|
12
|
-
pool =
|
13
|
-
|
11
|
+
def pmap(pool_or_size=Celluloid.cores, &block)
|
12
|
+
pool = if pool_or_size.class.ancestors.include?(Celluloid::PoolManager)
|
13
|
+
pool_or_size
|
14
|
+
else
|
15
|
+
Pmap::ParallelMapWorker.pool(size: pool_or_size)
|
16
|
+
end
|
17
|
+
futures = map { |elem| pool.future(:yielder, elem, block) }
|
14
18
|
futures.map { |future| future.value }
|
15
19
|
end
|
16
20
|
|
@@ -3,12 +3,12 @@ require 'celluloid/pmap/parallel_map_worker'
|
|
3
3
|
describe Celluloid::Pmap::ParallelMapWorker do
|
4
4
|
|
5
5
|
it "should execute the block we send" do
|
6
|
-
result = subject.yielder { 6 + 3 }
|
6
|
+
result = subject.yielder(proc { 6 + 3 })
|
7
7
|
result.should eq(9)
|
8
8
|
end
|
9
9
|
|
10
10
|
it "should send in the argument to the block" do
|
11
|
-
result = subject.yielder(6) {
|
11
|
+
result = subject.yielder(6, ->(e) { e + 3 })
|
12
12
|
result.should eq(9)
|
13
13
|
end
|
14
14
|
end
|
data/spec/celluloid/pmap_spec.rb
CHANGED
@@ -40,6 +40,13 @@ describe Celluloid::Pmap do
|
|
40
40
|
}.to take_approximately(1).seconds
|
41
41
|
end
|
42
42
|
|
43
|
+
let(:pool) { Celluloid::Pmap::ParallelMapWorker.pool(size: 10) }
|
44
|
+
it 'can reuse an existing thread pool' do
|
45
|
+
expect {
|
46
|
+
[1,2,3,4,5,6].pmap(pool) {|x| x; sleep(1) }
|
47
|
+
}.to take_approximately(1).seconds
|
48
|
+
end
|
49
|
+
|
43
50
|
it 'should be included in enumerable' do
|
44
51
|
Enumerable.ancestors.should include(Celluloid::Pmap)
|
45
52
|
end
|
@@ -1,15 +1,17 @@
|
|
1
1
|
require 'benchmark'
|
2
2
|
|
3
|
-
RSpec::Matchers.define :take_approximately do |
|
3
|
+
RSpec::Matchers.define :take_approximately do |expected|
|
4
4
|
chain :seconds do; end
|
5
5
|
|
6
6
|
match do |block|
|
7
7
|
@elapsed = Benchmark.realtime do
|
8
8
|
block.call
|
9
9
|
end
|
10
|
-
@elapsed.should be_within(0.2).of(
|
10
|
+
@elapsed.should be_within(0.2).of(expected)
|
11
11
|
end
|
12
12
|
|
13
|
+
supports_block_expectations if respond_to? :supports_block_expectations
|
14
|
+
|
13
15
|
failure_message_for_should do |actual|
|
14
16
|
"expected block to take about #{expected} seconds, but took #{@elapsed}"
|
15
17
|
end
|
@@ -19,7 +21,7 @@ RSpec::Matchers.define :take_approximately do |n|
|
|
19
21
|
end
|
20
22
|
|
21
23
|
description do
|
22
|
-
"take approximately #{
|
24
|
+
"take approximately #{expected} seconds to execute"
|
23
25
|
end
|
24
26
|
|
25
27
|
end
|
metadata
CHANGED
@@ -1,62 +1,69 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: celluloid-pmap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.2.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Jesse Wolgamott
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2015-03-31 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: celluloid
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- - ~>
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version: '0.
|
19
|
+
version: '0.16'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- - ~>
|
24
|
+
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version: '0.
|
26
|
+
version: '0.16'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: rake
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - ">="
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - ">="
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: rspec
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.99'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.99'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
52
60
|
- !ruby/object:Gem::Version
|
53
61
|
version: '0'
|
54
62
|
type: :development
|
55
63
|
prerelease: false
|
56
64
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
65
|
requirements:
|
59
|
-
- -
|
66
|
+
- - ">="
|
60
67
|
- !ruby/object:Gem::Version
|
61
68
|
version: '0'
|
62
69
|
description: Easy Parallel Executing using Celluloid
|
@@ -66,9 +73,9 @@ executables: []
|
|
66
73
|
extensions: []
|
67
74
|
extra_rdoc_files: []
|
68
75
|
files:
|
69
|
-
- .gitignore
|
70
|
-
- .rspec
|
71
|
-
- .travis.yml
|
76
|
+
- ".gitignore"
|
77
|
+
- ".rspec"
|
78
|
+
- ".travis.yml"
|
72
79
|
- Gemfile
|
73
80
|
- LICENSE.txt
|
74
81
|
- README.md
|
@@ -84,34 +91,27 @@ files:
|
|
84
91
|
homepage: https://github.com/jwo/celluloid-pmap
|
85
92
|
licenses:
|
86
93
|
- MIT
|
94
|
+
metadata: {}
|
87
95
|
post_install_message:
|
88
96
|
rdoc_options: []
|
89
97
|
require_paths:
|
90
98
|
- lib
|
91
99
|
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
-
none: false
|
93
100
|
requirements:
|
94
|
-
- -
|
101
|
+
- - ">="
|
95
102
|
- !ruby/object:Gem::Version
|
96
103
|
version: '0'
|
97
|
-
segments:
|
98
|
-
- 0
|
99
|
-
hash: 1634678292580827716
|
100
104
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
-
none: false
|
102
105
|
requirements:
|
103
|
-
- -
|
106
|
+
- - ">="
|
104
107
|
- !ruby/object:Gem::Version
|
105
108
|
version: '0'
|
106
|
-
segments:
|
107
|
-
- 0
|
108
|
-
hash: 1634678292580827716
|
109
109
|
requirements: []
|
110
110
|
rubyforge_project:
|
111
|
-
rubygems_version:
|
111
|
+
rubygems_version: 2.4.5
|
112
112
|
signing_key:
|
113
|
-
specification_version:
|
114
|
-
summary:
|
113
|
+
specification_version: 4
|
114
|
+
summary: 'Celluloid Futures are wicked sweet, and when combined with a #pmap implementation
|
115
115
|
AND a supervisor to keep the max threads down, you can be wicked sweet too!'
|
116
116
|
test_files:
|
117
117
|
- spec/celluloid/pmap/parallel_map_worker_spec.rb
|