pacer-parallel 0.1.0-java → 0.2.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +26 -17
- data/project.clj +1 -1
- data/src/clojure/pacer/parallel.clj +12 -0
- data/src/java/com/xnlogic/pacer/ChannelCapPipe.java +15 -2
- data/src/java/com/xnlogic/pacer/ChannelFanInPipe.java +17 -1
- data/src/java/com/xnlogic/pacer/ChannelReaderPipe.java +29 -4
- data/src/ruby/pacer/parallel/version.rb +2 -1
- data/target/release/{pacer.parallel-0.1.0-SNAPSHOT-standalone.jar → pacer.parallel-0.2.0-SNAPSHOT-standalone.jar} +0 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 49501e461707e82d8442a765a9d85e5c3d6116fa
|
4
|
+
data.tar.gz: 14c307841f53a72eac941344f8aed4da07e333db
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e6f8de6c827d83f70752055cccdd6e46c2af7831320725fe2b01164bc4e941fef876ea501e8a356e6fe0b5ad211f1fa609c9c416143bc6f95be298a205df5c2
|
7
|
+
data.tar.gz: 1ec244e49d3b9a50518ae2df7634da3715c11ccf715be4802e9f81eafd68ca8483d4252500569796034c46be0c511b6c58539ccc56fff71cf83b30b0dd703cda
|
data/README.md
CHANGED
@@ -2,6 +2,23 @@
|
|
2
2
|
|
3
3
|
Parallelize [Pacer](https://github.com/pangloss/pacer) Routes.
|
4
4
|
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
The following will create a route that will do the operation in the block in 2 parallel threads, while consuming the source data and
|
8
|
+
enqueueing it for consumption by those threads in one additional thread:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
g.v.parallel { |v| v.some_expensive_operation }
|
12
|
+
```
|
13
|
+
|
14
|
+
There are a few simple options, all optional. By default in_buffer is equal to the number of threads, and output is not buffered.
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
g.v.parallel(threads: 8, in_buffer: 4, out_buffer: 10) do |v|
|
18
|
+
v.all(&:out)
|
19
|
+
end
|
20
|
+
```
|
21
|
+
|
5
22
|
## Installation
|
6
23
|
|
7
24
|
Add this line to your application's Gemfile:
|
@@ -16,20 +33,10 @@ Or install it yourself as:
|
|
16
33
|
|
17
34
|
$ gem install pacer-parallel
|
18
35
|
|
19
|
-
## Usage
|
20
|
-
|
21
|
-
```ruby
|
22
|
-
g.v.parallel(threads: 8, in_buffer: 4, out_buffer: 10) do |v|
|
23
|
-
v.all(&:out)
|
24
|
-
end
|
25
|
-
```
|
26
|
-
|
27
36
|
## Contributing
|
28
37
|
|
29
38
|
1. Fork it
|
30
|
-
|
31
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
32
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
39
|
+
...
|
33
40
|
5. Create new Pull Request
|
34
41
|
|
35
42
|
|
@@ -45,21 +52,22 @@ Or install it yourself as:
|
|
45
52
|
it configurable.
|
46
53
|
* standard copy split pipe can push the channel to subchannels
|
47
54
|
* each parallel route pulls from the channel.
|
48
|
-
|
49
|
-
|
50
|
-
|
55
|
+
* in a go block (waits will not block go thread pool)
|
56
|
+
* ChannelReaderPipe
|
57
|
+
* PathChannelReaderPipe
|
51
58
|
* parallel routes are unmodified
|
52
59
|
* cap each route - eagerly consume input and push into a channel
|
53
|
-
|
60
|
+
* ChannelCapPipe again
|
54
61
|
* ExhaustMergePipe + GatherPipe to create a route to an list of
|
55
62
|
channels
|
56
63
|
* use alts to read from any of the channels
|
57
|
-
|
64
|
+
* ChannelFanInPipe
|
58
65
|
|
59
66
|
|
60
67
|
|
61
68
|
## Pipe structure built to create parallel route:
|
62
69
|
|
70
|
+
```
|
63
71
|
CCP
|
64
72
|
CSP (parallelism is 1 thread per pipe being split into)
|
65
73
|
CRP -> Work ... -> CCP
|
@@ -67,4 +75,5 @@ it configurable.
|
|
67
75
|
...
|
68
76
|
EMP
|
69
77
|
GP
|
70
|
-
|
78
|
+
CFIP
|
79
|
+
```
|
data/project.clj
CHANGED
@@ -14,6 +14,18 @@
|
|
14
14
|
(close! c))
|
15
15
|
c))
|
16
16
|
|
17
|
+
(defn pipe->path-chan [^Pipe pipe buffer]
|
18
|
+
(let [c (if buffer (chan buffer) (chan))]
|
19
|
+
(if (.hasNext pipe)
|
20
|
+
(future
|
21
|
+
(loop [v (.next pipe) path (.getCurrentPath pipe)]
|
22
|
+
(when v (>!! c path))
|
23
|
+
(if (.hasNext pipe)
|
24
|
+
(recur (.next pipe) (.getCurrentPath pipe))
|
25
|
+
(close! c))))
|
26
|
+
(close! c))
|
27
|
+
c))
|
28
|
+
|
17
29
|
(defn chan-select [chans]
|
18
30
|
(let [[v c] (alts!! chans)]
|
19
31
|
(if v
|
@@ -8,10 +8,13 @@ import com.tinkerpop.pipes.util.FastNoSuchElementException;
|
|
8
8
|
import clojure.lang.RT;
|
9
9
|
import clojure.lang.Var;
|
10
10
|
import clojure.lang.Symbol;
|
11
|
+
import java.util.List;
|
12
|
+
import java.util.ArrayList;
|
11
13
|
|
12
14
|
public class ChannelCapPipe<S> extends AbstractPipe<S, Object> implements TransformPipe<S, Object> {
|
13
15
|
private static final Var REQUIRE = RT.var("clojure.core", "require");
|
14
16
|
private static final Var PIPE_TO_CHAN = RT.var("pacer.parallel", "pipe->chan");
|
17
|
+
private static final Var PIPE_TO_PATH_CHAN = RT.var("pacer.parallel", "pipe->path-chan");
|
15
18
|
private static boolean environmentReady = false;
|
16
19
|
|
17
20
|
public static void setupEnvironment() {
|
@@ -23,7 +26,6 @@ public class ChannelCapPipe<S> extends AbstractPipe<S, Object> implements Transf
|
|
23
26
|
}
|
24
27
|
}
|
25
28
|
|
26
|
-
|
27
29
|
private Object buffer;
|
28
30
|
private boolean hasRun = false;
|
29
31
|
|
@@ -35,12 +37,23 @@ public class ChannelCapPipe<S> extends AbstractPipe<S, Object> implements Transf
|
|
35
37
|
protected Object processNextStart() {
|
36
38
|
if (!this.hasRun) {
|
37
39
|
this.hasRun = true;
|
38
|
-
|
40
|
+
if (this.pathEnabled) {
|
41
|
+
return PIPE_TO_PATH_CHAN.invoke(starts, buffer);
|
42
|
+
} else {
|
43
|
+
return PIPE_TO_CHAN.invoke(starts, buffer);
|
44
|
+
}
|
39
45
|
} else {
|
40
46
|
throw FastNoSuchElementException.instance();
|
41
47
|
}
|
42
48
|
}
|
43
49
|
|
50
|
+
// If path is enabled, the path will be pushed into the channel.
|
51
|
+
// Having a path available here as well causes the merge pipe to
|
52
|
+
// produce a messed up path.
|
53
|
+
public List getCurrentPath() {
|
54
|
+
return new ArrayList();
|
55
|
+
}
|
56
|
+
|
44
57
|
public void reset() {
|
45
58
|
this.hasRun = false;
|
46
59
|
}
|
@@ -15,6 +15,7 @@ public class ChannelFanInPipe<S> extends AbstractPipe<List<Object>, S> implement
|
|
15
15
|
private static final Var CHAN_SELECT = RT.var("pacer.parallel", "chan-select");
|
16
16
|
|
17
17
|
private Object chans;
|
18
|
+
private List currentPath;
|
18
19
|
|
19
20
|
protected S processNextStart() {
|
20
21
|
while (true) {
|
@@ -28,13 +29,28 @@ public class ChannelFanInPipe<S> extends AbstractPipe<List<Object>, S> implement
|
|
28
29
|
this.chans = null;
|
29
30
|
} else {
|
30
31
|
this.chans = NTH.invoke(vec, 1);
|
31
|
-
|
32
|
+
if (this.pathEnabled) {
|
33
|
+
this.currentPath = (List) NTH.invoke(vec, 0);
|
34
|
+
System.out.println(this.currentPath);
|
35
|
+
return (S) this.currentPath.get(this.currentPath.size() - 1);
|
36
|
+
} else {
|
37
|
+
return (S) NTH.invoke(vec, 0);
|
38
|
+
}
|
32
39
|
}
|
33
40
|
}
|
34
41
|
}
|
35
42
|
}
|
36
43
|
|
44
|
+
public List getCurrentPath() {
|
45
|
+
if (this.pathEnabled) {
|
46
|
+
return this.currentPath;
|
47
|
+
} else {
|
48
|
+
throw new RuntimeException(Pipe.NO_PATH_MESSAGE);
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
37
52
|
public void reset() {
|
53
|
+
this.currentPath = null;
|
38
54
|
this.chans = null;
|
39
55
|
}
|
40
56
|
}
|
@@ -7,27 +7,52 @@ import com.tinkerpop.pipes.util.FastNoSuchElementException;
|
|
7
7
|
|
8
8
|
import clojure.lang.RT;
|
9
9
|
import clojure.lang.Var;
|
10
|
+
import java.util.List;
|
10
11
|
|
11
|
-
public class ChannelReaderPipe<S> extends AbstractPipe<
|
12
|
+
public class ChannelReaderPipe<S> extends AbstractPipe<Object, S> implements TransformPipe<Object, S> {
|
12
13
|
private static final Var READ_CHAN = RT.var("clojure.core.async", "<!!");
|
13
14
|
|
14
15
|
private Object chan;
|
16
|
+
private List currentPath;
|
15
17
|
|
16
|
-
protected
|
18
|
+
protected S processNextStart() {
|
17
19
|
while (true) {
|
18
20
|
if (this.chan == null) {
|
19
21
|
this.chan = starts.next();
|
20
22
|
} else {
|
21
|
-
Object value
|
23
|
+
Object value;
|
24
|
+
if (this.pathEnabled) {
|
25
|
+
this.currentPath = (List) READ_CHAN.invoke(this.chan);
|
26
|
+
if (this.currentPath != null) {
|
27
|
+
value = this.currentPath.get(this.currentPath.size() - 1);
|
28
|
+
} else {
|
29
|
+
value = null;
|
30
|
+
}
|
31
|
+
} else {
|
32
|
+
value = READ_CHAN.invoke(this.chan);
|
33
|
+
}
|
22
34
|
if (value == null)
|
23
35
|
this.chan = null;
|
24
36
|
else
|
25
|
-
return value;
|
37
|
+
return (S) value;
|
26
38
|
}
|
27
39
|
}
|
28
40
|
}
|
29
41
|
|
42
|
+
public List getCurrentPath() {
|
43
|
+
if (this.pathEnabled) {
|
44
|
+
return this.currentPath;
|
45
|
+
} else {
|
46
|
+
throw new RuntimeException(Pipe.NO_PATH_MESSAGE);
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
protected List getPathToHere() {
|
51
|
+
return this.currentPath;
|
52
|
+
}
|
53
|
+
|
30
54
|
public void reset() {
|
55
|
+
this.currentPath = null;
|
31
56
|
this.chan = null;
|
32
57
|
}
|
33
58
|
}
|
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pacer-parallel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Darrick Wiebe
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-08-
|
11
|
+
date: 2013-08-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pacer
|
@@ -77,7 +77,7 @@ files:
|
|
77
77
|
- src/ruby/pacer/parallel/channel_fan_in.rb
|
78
78
|
- src/ruby/pacer/parallel/channel_reader.rb
|
79
79
|
- src/ruby/pacer/parallel/version.rb
|
80
|
-
- target/release/pacer.parallel-0.
|
80
|
+
- target/release/pacer.parallel-0.2.0-SNAPSHOT-standalone.jar
|
81
81
|
homepage: http://xnlogic.com
|
82
82
|
licenses:
|
83
83
|
- MIT
|