You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by ok...@apache.org on 2017/01/26 22:02:10 UTC
tinkerpop git commit: added a butt load more test cases verifying
will crazy corner cases.
Repository: tinkerpop
Updated Branches:
refs/heads/TINKERPOP-1617 5ecefff00 -> 44e418610
added a butt load more test cases verifying will crazy corner cases.
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/44e41861
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/44e41861
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/44e41861
Branch: refs/heads/TINKERPOP-1617
Commit: 44e418610502d0d94c477c53974e9adb1ddb780d
Parents: 5ecefff
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Thu Jan 26 15:02:05 2017 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Thu Jan 26 15:02:05 2017 -0700
----------------------------------------------------------------------
.../optimization/SingleIterationStrategy.java | 22 ++++++++-----
.../SingleIterationStrategyTest.java | 34 ++++++++++++++------
.../SparkSingleIterationStrategy.java | 17 +++++-----
.../SparkSingleIterationStrategyTest.java | 26 ++++++++++++++-
4 files changed, 73 insertions(+), 26 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/44e41861/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/optimization/SingleIterationStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/optimization/SingleIterationStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/optimization/SingleIterationStrategy.java
index efcbe9a..19d9854 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/optimization/SingleIterationStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/optimization/SingleIterationStrategy.java
@@ -29,9 +29,11 @@ import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTrav
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
import org.apache.tinkerpop.gremlin.process.traversal.step.Barrier;
import org.apache.tinkerpop.gremlin.process.traversal.step.LambdaHolder;
+import org.apache.tinkerpop.gremlin.process.traversal.step.SideEffectCapable;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
import org.apache.tinkerpop.gremlin.process.traversal.step.branch.LocalStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeVertexStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.LambdaFlatMapStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.LambdaMapStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep;
@@ -41,6 +43,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.Adja
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.FilterRankingStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.IncidentToAdjacentStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.InlineFilterStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.Graph;
@@ -93,22 +96,25 @@ public final class SingleIterationStrategy extends AbstractTraversalStrategy<Tra
final boolean beyondStarGraph =
TraversalHelper.hasStepOfAssignableClassRecursively(Scope.global, LambdaHolder.class, computerTraversal) ||
!TraversalHelper.isLocalStarGraph(computerTraversal);
- if (!beyondStarGraph && // if we move beyond the star graph, then localization is not possible.
- !(computerTraversal.getStartStep().getNextStep() instanceof EmptyStep) && // if its just a g.V()/E(), then don't localize
- !(computerTraversal.getStartStep().getNextStep() instanceof LocalStep) && // removes the potential for the infinite recursive application of the traversal
- !(computerTraversal.getStartStep().getNextStep() instanceof Barrier) && // if the second step is a barrier, no point in trying to localize anything
- !(TraversalHelper.getStepsOfAssignableClass(TraversalParent.class, computerTraversal). // this is a strict precaution that could be loosed with deeper logic on barriers in global children
+ if (!beyondStarGraph && // if we move beyond the star graph, then localization is not possible.
+ (computerTraversal.getStartStep() instanceof GraphStep) && // while GraphComputer requires GraphStep starts, this is just a precaution when inject() starts are supported
+ !(computerTraversal.getStartStep().getNextStep() instanceof EmptyStep) && // if its just a g.V()/E(), then don't localize
+ !(computerTraversal.getStartStep().getNextStep() instanceof LocalStep) && // removes the potential for the infinite recursive application of the traversal
+ !(computerTraversal.getStartStep().getNextStep() instanceof Barrier) && // if the second step is a barrier, no point in trying to localize anything
+ !computerTraversal.getTraverserRequirements().contains(TraverserRequirement.LABELED_PATH) && // this is to alleviate issues with DetachedElement in paths (TODO: when detachment is dynamic, remove this)
+ !computerTraversal.getTraverserRequirements().contains(TraverserRequirement.PATH) && // this is to alleviate issues with DetachedElement in paths (TODO: when detachment is dynamic, remove this)
+ TraversalHelper.getStepsOfAssignableClassRecursively(SideEffectCapable.class, computerTraversal).isEmpty() && // this is to alleviate issues with DetachedElement in paths (TODO: when detachment is dynamic, remove this)
+ !(TraversalHelper.getStepsOfAssignableClass(TraversalParent.class, computerTraversal). // this is a strict precaution that could be loosed with deeper logic on barriers in global children
stream().
filter(parent -> !parent.getGlobalChildren().isEmpty()).findAny().isPresent())) {
final Traversal.Admin<?, ?> newComputerTraversal = step.computerTraversal.getPure();
final Traversal.Admin localTraversal = new DefaultGraphTraversal<>();
final Step barrier = (Step) TraversalHelper.getFirstStepOfAssignableClass(Barrier.class, newComputerTraversal).orElse(null);
- final Step endStep = null == barrier ? newComputerTraversal.getEndStep() : barrier.getPreviousStep();
- if (!(endStep instanceof VertexStep || endStep instanceof EdgeVertexStep)) {
+ if (null == barrier || !(barrier instanceof TraversalParent && (barrier.getPreviousStep() instanceof VertexStep || barrier.getPreviousStep() instanceof EdgeVertexStep))) {
TraversalHelper.removeToTraversal(newComputerTraversal.getStartStep().getNextStep(), null == barrier ? EmptyStep.instance() : barrier, localTraversal);
assert !localTraversal.getSteps().isEmpty(); // given the if() constraints, this is impossible
- if (localTraversal.getSteps().size() > 1) { // if its just a single step, a local wrap will not alter its locus of computation
+ if (localTraversal.getSteps().size() > 1) { // if its just a single step, a local wrap will not alter its locus of computation
if (null == barrier)
TraversalHelper.insertTraversal(0, (Traversal.Admin) __.local(localTraversal), newComputerTraversal);
else
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/44e41861/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/optimization/SingleIterationStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/optimization/SingleIterationStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/optimization/SingleIterationStrategyTest.java
index 612fb9d..09887f3 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/optimization/SingleIterationStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/computer/traversal/strategy/optimization/SingleIterationStrategyTest.java
@@ -27,6 +27,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTrav
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.AdjacentToIncidentStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies;
+import org.apache.tinkerpop.gremlin.structure.Column;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -35,6 +36,10 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.in;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.inE;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.out;
+import static org.apache.tinkerpop.gremlin.structure.Column.keys;
import static org.junit.Assert.assertEquals;
/**
@@ -77,8 +82,9 @@ public class SingleIterationStrategyTest {
{__.V().id(), __.V().id(), Collections.emptyList()},
{__.V().out().count(), __.V().out().count(), Collections.emptyList()},
{__.V().out().label().count(), __.V().out().label().count(), Collections.emptyList()},
- {__.V().in().id(), __.V().local(__.in().id()), Collections.emptyList()},
- {__.V().out().id(), __.V().local(__.out().id()), Collections.emptyList()},
+ {__.V().in().id(), __.V().local(in().id()), Collections.emptyList()},
+ {in().id(), in().id(), Collections.emptyList()}, // test inject
+ {__.V().out().id(), __.V().local(out().id()), Collections.emptyList()},
{__.V().both().id(), __.V().local(__.both().id()), Collections.emptyList()},
{__.V().outE().inV().id().count(), __.V().local(__.outE().inV().id()).count(), Collections.emptyList()},
{__.V().map(__.outE().inV()).count(), __.V().map(__.outE().inV()).count(), Collections.emptyList()},
@@ -86,15 +92,25 @@ public class SingleIterationStrategyTest {
{__.V().outE().map(__.inV()).id().count(), __.V().outE().map(__.inV()).id().count(), Collections.emptyList()},
{__.V().outE().map(__.inV()).count(), __.V().outE().map(__.inV()).count(), Collections.emptyList()},
{__.V().outE().map(__.inV()).values("name").count(), __.V().outE().map(__.inV()).values("name").count(), Collections.emptyList()},
- {__.V().outE().inV().count(), __.V().outE().inV().count(), Collections.emptyList()},
- {__.V().out().id().count(), __.V().local(__.out().id()).count(), Collections.emptyList()},
- {__.V().in().id().count(), __.V().local(__.in().id()).count(), Collections.emptyList()},
- {__.V().in().id().select("id-map").dedup().count(), __.V().local(__.in().id().select("id-map")).dedup().count(), Collections.emptyList()},
+ {__.V().outE().inV().count(), __.V().local(__.outE().inV()).count(), Collections.emptyList()},
+ {__.V().out().id().count(), __.V().local(out().id()).count(), Collections.emptyList()},
+ {__.V().in().id().count(), __.V().local(in().id()).count(), Collections.emptyList()},
+ {__.V().in().id().select("id-map").dedup().count(), __.V().local(in().id().select("id-map")).dedup().count(), Collections.emptyList()},
+ {__.V().in().id().groupCount().select(keys).unfold().dedup().count(), __.V().local(in().id()).groupCount().select(keys).unfold().dedup().count(), Collections.emptyList()},
{__.V().outE().values("weight"), __.V().outE().values("weight"), Collections.emptyList()},
{__.V().outE().values("weight").sum(), __.V().outE().values("weight").sum(), Collections.emptyList()},
- {__.V().inE().values("weight"), __.V().local(__.inE().values("weight")), Collections.emptyList()},
- {__.V().inE().values("weight").sum(), __.V().local(__.inE().values("weight")).sum(), Collections.emptyList()},
- {__.V().inE().values("weight").sum().dedup().count(), __.V().local(__.inE().values("weight")).sum().dedup().count(), Collections.emptyList()},
+ {__.V().inE().values("weight"), __.V().local(inE().values("weight")), Collections.emptyList()},
+ {__.V().inE().values("weight").sum(), __.V().local(inE().values("weight")).sum(), Collections.emptyList()},
+ {__.V().inE().values("weight").sum().dedup().count(), __.V().local(inE().values("weight")).sum().dedup().count(), Collections.emptyList()},
+ {__.V().as("a").out("knows").as("b").select("a", "b"), __.V().as("a").out("knows").as("b").select("a", "b"), Collections.emptyList()},
+ {__.V().out().groupCount("x").cap("x"), __.V().out().groupCount("x").cap("x"), Collections.emptyList()},
+ {__.V().outE().inV().groupCount().select(Column.values).unfold().dedup().count(), __.V().outE().inV().groupCount().select(Column.values).unfold().dedup().count(), Collections.emptyList()},
+ {__.V().outE().inV().groupCount(), __.V().outE().inV().groupCount(), Collections.emptyList()},
+ {__.V().outE().inV().groupCount().by("name"), __.V().outE().inV().groupCount().by("name"), Collections.emptyList()},
+ {__.V().inE().id().groupCount(), __.V().local(inE().id()).groupCount(), Collections.emptyList()},
+ {__.V().inE().values("weight").groupCount(), __.V().local(inE().values("weight")).groupCount(), Collections.emptyList()},
+ {__.V().outE().inV().tree(), __.V().outE().inV().tree(), Collections.emptyList()},
+ {__.V().in().values("name").groupCount(), __.V().in().values("name").groupCount(), Collections.emptyList()}
});
}
}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/44e41861/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/SparkSingleIterationStrategy.java
----------------------------------------------------------------------
diff --git a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/SparkSingleIterationStrategy.java b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/SparkSingleIterationStrategy.java
index 2abb9b8..1288b0d 100644
--- a/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/SparkSingleIterationStrategy.java
+++ b/spark-gremlin/src/main/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/SparkSingleIterationStrategy.java
@@ -33,14 +33,13 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeVertexStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.LambdaFlatMapStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.LambdaMapStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectOneStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.SelectStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalFlatMapStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalMapStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffectStep;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.Graph;
@@ -83,7 +82,10 @@ public final class SparkSingleIterationStrategy extends AbstractTraversalStrateg
}
}
}
- if (!doesMessagePass && !SparkSingleIterationStrategy.endsWithInElement(computerTraversal)) {
+ if (!doesMessagePass &&
+ !SparkSingleIterationStrategy.endsWithInElement(computerTraversal) &&
+ !(computerTraversal.getTraverserRequirements().contains(TraverserRequirement.LABELED_PATH) || // todo: remove this when dynamic detachment is available in 3.3.0
+ computerTraversal.getTraverserRequirements().contains(TraverserRequirement.PATH))) { // todo: remove this when dynamic detachment is available in 3.3.0
step.setComputer(step.getComputer()
// if no message passing, don't partition the loaded graph
.configure(Constants.GREMLIN_SPARK_SKIP_PARTITIONER, true)
@@ -95,6 +97,9 @@ public final class SparkSingleIterationStrategy extends AbstractTraversalStrateg
private static final boolean endsWithInElement(final Traversal.Admin<?, ?> traversal) {
Step<?, ?> current = traversal.getEndStep();
+ while (current instanceof Barrier) { // clip off any tail barriers
+ current = current.getPreviousStep();
+ }
while (!(current instanceof EmptyStep)) {
if ((current instanceof VertexStep && (((VertexStep) current).returnsVertex() ||
!((VertexStep) current).getDirection().equals(Direction.OUT))) ||
@@ -107,11 +112,7 @@ public final class SparkSingleIterationStrategy extends AbstractTraversalStrateg
if (((TraversalParent) current).getGlobalChildren().stream().filter(SparkSingleIterationStrategy::endsWithInElement).findAny().isPresent())
return true;
}
- if (!(current instanceof FilterStep ||
- current instanceof SideEffectStep ||
- current instanceof SelectStep ||
- current instanceof SelectOneStep ||
- current instanceof Barrier)) {
+ if (!(current instanceof FilterStep || current instanceof SideEffectStep)) { // side-effects and filters do not alter the mapping and thus, deeper analysis is required
return false;
}
current = current.getPreviousStep();
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/44e41861/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/SparkSingleIterationStrategyTest.java
----------------------------------------------------------------------
diff --git a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/SparkSingleIterationStrategyTest.java b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/SparkSingleIterationStrategyTest.java
index 20596d7..b055eb8 100644
--- a/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/SparkSingleIterationStrategyTest.java
+++ b/spark-gremlin/src/test/java/org/apache/tinkerpop/gremlin/spark/process/computer/traversal/strategy/optimization/SparkSingleIterationStrategyTest.java
@@ -43,6 +43,7 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
+import static org.apache.tinkerpop.gremlin.structure.Column.keys;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -127,12 +128,23 @@ public class SparkSingleIterationStrategyTest extends AbstractSparkTest {
test(true, 6L, g.V().inE().id().count());
test(true, 6L, g.V().outE().count());
test(true, 4L, g.V().outE().inV().id().dedup().count());
- test(true, 6L, g.V().as("a").outE().inV().as("b").id().dedup("a", "b").by(T.id).count());
test(true, 4L, g.V().filter(__.in()).count());
test(true, 6L, g.V().sideEffect(__.in()).count());
+ test(true, 6L, g.V().map(__.constant("hello")).count());
+ test(true, g.V().groupCount());
+ test(true, g.V().groupCount("x"));
+ test(true, g.V().groupCount("x").cap("x"));
+ test(true, g.V().id().groupCount("x").cap("x"));
+ test(true, g.V().outE().groupCount());
+ test(true, g.V().outE().groupCount().by("weight"));
+ test(true, g.V().inE().id().groupCount());
+ test(true, g.V().inE().values("weight").groupCount());
/////
+ test(false, 6L, g.V().as("a").outE().inV().as("b").id().dedup("a", "b").by(T.id).count());
test(false, 6L, g.V().local(__.inE()).count());
test(false, 6L, g.V().outE().outV().count()); // todo: low probability traversal, but none the less could be optimized for
+ test(false, g.V().out().id().groupCount("x")); // todo: low probability traversal, but none the less could be optimized for
+ test(false, g.V().inE().values("weight").groupCount("x")); // todo: low probability traversal, but none the less could be optimized for
test(false, 6L, g.V().in().count());
test(false, 6L, g.V().flatMap(__.in()).count());
test(false, 4L, g.V().map(__.in()).count());
@@ -150,6 +162,18 @@ public class SparkSingleIterationStrategyTest extends AbstractSparkTest {
test(false, g.V().out().valueMap());
test(false, 6L, g.V().as("a").outE().inV().values("name").as("b").dedup("a", "b").count());
test(false, 2L, g.V().outE().inV().groupCount().select(Column.values).unfold().dedup().count());
+ test(false, g.V().out().groupCount("x"));
+ test(false, g.V().out().groupCount("x").cap("x"));
+ test(false, 6L, g.V().both().groupCount("x").cap("x").select(keys).unfold().count());
+ test(false, g.V().outE().inV().groupCount());
+ test(false, g.V().outE().inV().groupCount().by("name"));
+ test(false, g.V().outE().inV().tree());
+ test(false, g.V().inE().groupCount());
+ test(false, g.V().inE().groupCount().by("weight"));
+ test(false, g.V().in().values("name").groupCount());
+ test(false, g.V().out().groupCount("x"));
+ test(false, g.V().in().groupCount("x"));
+ test(false, g.V().both().groupCount("x").cap("x"));
}
private static <R> void test(boolean singleIteration, final Traversal<?, R> traversal) {