pacer-parallel 0.1.0-java → 0.2.0-java
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.
- 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
|