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 2016/06/28 16:44:39 UTC

tinkerpop git commit: added RepeatUnrollStrategy for when the loop amount is known at compile time. Fixed a bug in BranchStep around child integration.

Repository: tinkerpop
Updated Branches:
  refs/heads/TINKERPOP-1349 [created] 8753366a9


added RepeatUnrollStrategy for when the loop amount is known at compile time. Fixed a bug in BranchStep around child integration.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/8753366a
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/8753366a
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/8753366a

Branch: refs/heads/TINKERPOP-1349
Commit: 8753366a975101ba4edaa1888163abda3238f7ff
Parents: 0787e46
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Tue Jun 28 10:44:32 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Tue Jun 28 10:44:32 2016 -0600

----------------------------------------------------------------------
 .../process/traversal/TraversalStrategies.java  |   2 +
 .../traversal/step/branch/BranchStep.java       |  12 +-
 .../optimization/RepeatUnrollStrategy.java      |  75 +++++++++
 .../IdentityRemovalStrategyTest.java            |  35 ++++-
 .../optimization/RepeatUnrollStrategyTest.java  | 154 +++++++++++++++++++
 .../process/traversal/step/map/ProfileTest.java |  36 +++--
 6 files changed, 291 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8753366a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
index 137abb9..b093676 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
@@ -30,6 +30,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.Matc
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.OrderLimitStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathProcessorStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RepeatUnrollStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ComputerVerificationStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.StandardVerificationStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies;
@@ -193,6 +194,7 @@ public interface TraversalStrategies extends Serializable, Cloneable {
                     FilterRankingStrategy.instance(),
                     IdentityRemovalStrategy.instance(),
                     MatchPredicateStrategy.instance(),
+                    RepeatUnrollStrategy.instance(),
                     RangeByIsCountStrategy.instance(),
                     ProfileStrategy.instance(),
                     StandardVerificationStrategy.instance());

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8753366a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java
index 2cd954d..19df2a6 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/branch/BranchStep.java
@@ -165,18 +165,22 @@ public class BranchStep<S, E, M> extends ComputerAwareStep<S, E> implements Trav
                 final List<Traversal.Admin<S, E>> clonedTraversals = clone.traversalOptions.compute(entry.getKey(), (k, v) ->
                         (v == null) ? new ArrayList<>(traversals.size()) : v);
                 for (final Traversal.Admin<S, E> traversal : traversals) {
-                    final Traversal.Admin<S, E> clonedTraversal = traversal.clone();
-                    clonedTraversals.add(clonedTraversal);
-                    clone.integrateChild(clonedTraversal);
+                    clonedTraversals.add(traversal.clone());
                 }
             }
         }
         clone.branchTraversal = this.branchTraversal.clone();
-        clone.integrateChild(clone.branchTraversal);
         return clone;
     }
 
     @Override
+    public void setTraversal(final Traversal.Admin<?, ?> parentTraversal) {
+        super.setTraversal(parentTraversal);
+        this.integrateChild(this.branchTraversal);
+        this.traversalOptions.values().stream().flatMap(List::stream).forEach(this::integrateChild);
+    }
+
+    @Override
     public int hashCode() {
         int result = super.hashCode();
         if (this.traversalOptions != null)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8753366a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RepeatUnrollStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RepeatUnrollStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RepeatUnrollStrategy.java
new file mode 100644
index 0000000..9047478
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RepeatUnrollStrategy.java
@@ -0,0 +1,75 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.LoopTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.NoOpBarrierStep;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class RepeatUnrollStrategy extends AbstractTraversalStrategy<TraversalStrategy.OptimizationStrategy> implements TraversalStrategy.OptimizationStrategy {
+
+    private static final RepeatUnrollStrategy INSTANCE = new RepeatUnrollStrategy();
+
+    private RepeatUnrollStrategy() {
+    }
+
+    @Override
+    public void apply(final Traversal.Admin<?, ?> traversal) {
+        if (!TraversalHelper.hasStepOfAssignableClass(RepeatStep.class, traversal) ||
+                TraversalHelper.onGraphComputer(traversal))
+            return;
+
+        for (int i = 0; i < traversal.getSteps().size(); i++) {
+            if (traversal.getSteps().get(i) instanceof RepeatStep) {
+                final RepeatStep<?> repeatStep = (RepeatStep) traversal.getSteps().get(i);
+                if (null == repeatStep.getEmitTraversal() && repeatStep.getUntilTraversal() instanceof LoopTraversal) {
+                    final Traversal.Admin<?, ?> repeatTraversal = repeatStep.getGlobalChildren().get(0);
+                    final int repeatLength = repeatTraversal.getSteps().size() - 1;
+                    repeatTraversal.removeStep(repeatLength);
+                    int insertIndex = i;
+                    final int loops = (int) ((LoopTraversal) repeatStep.getUntilTraversal()).getMaxLoops();
+                    for (int j = 0; j < loops; j++) {
+                        TraversalHelper.insertTraversal(insertIndex, repeatTraversal.clone(), traversal); // removes the RepeatEndStep
+                        insertIndex = insertIndex + repeatLength + 1;
+                        traversal.addStep(insertIndex, new NoOpBarrierStep<>(traversal));
+                    }
+                    if (!repeatStep.getLabels().isEmpty()) {
+                        final Step<?, ?> lastStep = (Step) traversal.getSteps().get(insertIndex);
+                        repeatStep.getLabels().forEach(lastStep::addLabel);
+                    }
+                    traversal.removeStep(i); // remove the RepeatStep
+                }
+            }
+        }
+    }
+
+
+    public static RepeatUnrollStrategy instance() {
+        return INSTANCE;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8753366a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/IdentityRemovalStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/IdentityRemovalStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/IdentityRemovalStrategyTest.java
index fd1ec2b..c71ad99 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/IdentityRemovalStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/IdentityRemovalStrategyTest.java
@@ -22,6 +22,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies;
+import org.apache.tinkerpop.gremlin.util.TimeUtil;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -29,6 +30,8 @@ import org.junit.runners.Parameterized;
 import java.util.Arrays;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -36,6 +39,8 @@ import static org.junit.Assert.assertEquals;
 @RunWith(Parameterized.class)
 public class IdentityRemovalStrategyTest {
 
+    private static boolean executedshouldBeFaster = false;
+
     @Parameterized.Parameter(value = 0)
     public Traversal original;
 
@@ -43,7 +48,7 @@ public class IdentityRemovalStrategyTest {
     public Traversal optimized;
 
 
-    void applyIdentityRemovalStrategy(final Traversal traversal) {
+    private void applyIdentityRemovalStrategy(final Traversal traversal) {
         final TraversalStrategies strategies = new DefaultTraversalStrategies();
         strategies.addStrategies(IdentityRemovalStrategy.instance());
         traversal.asAdmin().setStrategies(strategies);
@@ -70,4 +75,30 @@ public class IdentityRemovalStrategyTest {
                 {__.out().identity().as("a").out().in().identity().identity().as("b").identity().out(), __.out().as("a").out().in().as("b").out()},
         });
     }
-}
\ No newline at end of file
+
+    @Test
+    public void shouldBeFaster() {
+        if (executedshouldBeFaster)
+            return;
+        else
+            executedshouldBeFaster = true;
+        final int startSize = 1000;
+        final int clockRuns = 1000;
+        final Integer[] starts = new Integer[startSize];
+        for (int i = 0; i < startSize; i++) {
+            starts[i] = i;
+        }
+
+        final Runnable original = () -> __.inject(starts).identity().identity().identity().identity().iterate();
+
+        final Runnable optimized = () -> {
+            final Traversal<Integer, Integer> traversal = __.inject(starts).identity().identity().identity().identity();
+            traversal.asAdmin().setStrategies(traversal.asAdmin().getStrategies().clone().addStrategies(IdentityRemovalStrategy.instance()));
+            traversal.iterate();
+        };
+
+        //System.out.println(TimeUtil.clock(clockRuns, original) + "---" + TimeUtil.clock(clockRuns,optimized));
+        assertTrue(TimeUtil.clock(clockRuns, original) > TimeUtil.clock(clockRuns, optimized));
+        assertTrue(TimeUtil.clock(clockRuns, optimized) < TimeUtil.clock(clockRuns, original));
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8753366a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RepeatUnrollStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RepeatUnrollStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RepeatUnrollStrategyTest.java
new file mode 100644
index 0000000..1c4c4b7
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RepeatUnrollStrategyTest.java
@@ -0,0 +1,154 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.util.TimeUtil;
+import org.javatuples.Pair;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Random;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+@RunWith(Parameterized.class)
+public class RepeatUnrollStrategyTest {
+
+    private static final Random RANDOM = new Random();
+    private static boolean shouldBeFasterWithUniqueStreamExecuted = false;
+    private static boolean shouldBeFasterWithDuplicateStreamExecuted = false;
+
+    @Parameterized.Parameter(value = 0)
+    public Traversal original;
+
+    @Parameterized.Parameter(value = 1)
+    public Traversal optimized;
+
+
+    private void applyRepeatUnrollStrategy(final Traversal traversal) {
+        final TraversalStrategies strategies = new DefaultTraversalStrategies();
+        strategies.addStrategies(RepeatUnrollStrategy.instance());
+        traversal.asAdmin().setStrategies(strategies);
+        traversal.asAdmin().applyStrategies();
+
+    }
+
+    @Test
+    public void doTest() {
+        applyRepeatUnrollStrategy(original);
+        assertEquals(optimized, original);
+    }
+
+    @Parameterized.Parameters(name = "{0}")
+    public static Iterable<Object[]> generateTestParameters() {
+
+        final Predicate<Traverser<Vertex>> predicate = t -> t.loops() > 5;
+        return Arrays.asList(new Traversal[][]{
+                {__.identity(), __.identity()},
+                {__.out().as("a").in().repeat(__.outE("created").bothV()).times(2).in(), __.out().as("a").in().outE("created").bothV().barrier().outE("created").bothV().barrier().in()},
+                {__.out().repeat(__.outE("created").bothV()).times(1).in(), __.out().outE("created").bothV().barrier().in()},
+                {__.repeat(__.outE("created").bothV()).times(1).in(), __.outE("created").bothV().barrier().in()},
+                {__.repeat(__.out()).times(2).as("x").repeat(__.in().as("b")).times(3), __.out().barrier().out().barrier().as("x").in().as("b").barrier().in().as("b").barrier().in().as("b").barrier()},
+                {__.repeat(__.outE("created").inV()).times(2), __.outE("created").inV().barrier().outE("created").inV().barrier()},
+                {__.repeat(__.out()).times(3), __.out().barrier().out().barrier().out().barrier()},
+                {__.repeat(__.local(__.select("a").out("knows"))).times(2), __.local(__.select("a").out("knows")).barrier().local(__.select("a").out("knows")).barrier()},
+                {__.<Vertex>times(2).repeat(__.out()), __.out().barrier().out().barrier()},
+                {__.<Vertex>out().times(2).repeat(__.out().as("a")).as("x"), __.out().out().as("a").barrier().out().as("a").barrier().as("x")},
+                {__.repeat(__.out()).emit().times(2), __.repeat(__.out()).emit().times(2)},
+                {__.repeat(__.out()).until(predicate), __.repeat(__.out()).until(predicate)},
+                {__.repeat(__.out()).until(predicate).repeat(__.out()).times(2), __.repeat(__.out()).until(predicate).out().barrier().out().barrier()},
+                {__.repeat(__.union(__.both(), __.identity())).times(2).out(), __.union(__.both(), __.identity()).barrier().union(__.both(), __.identity()).barrier().out()},
+        });
+    }
+
+    @Test
+    public void shouldBeFasterWithUniqueStream() {
+        if (shouldBeFasterWithUniqueStreamExecuted)
+            return;
+        shouldBeFasterWithUniqueStreamExecuted = true;
+        final int startSize = 1000;
+        final int clockRuns = 1000;
+        final Integer[] starts = new Integer[startSize];
+        for (int i = 0; i < startSize; i++) {
+            starts[i] = i; // 1000 unique objects
+        }
+        assertEquals(startSize, new HashSet<>(Arrays.asList(starts)).size());
+        clockTraversals(starts, clockRuns);
+    }
+
+    @Test
+    public void shouldBeFasterWithDuplicateStream() {
+        if (shouldBeFasterWithDuplicateStreamExecuted)
+            return;
+        shouldBeFasterWithDuplicateStreamExecuted = true;
+        final int startSize = 1000;
+        final int clockRuns = 1000;
+        final int uniques = 100;
+        final Integer[] starts = new Integer[startSize];
+        for (int i = 0; i < startSize; i++) {
+            starts[i] = i % uniques; // 100 unique objects
+        }
+        assertEquals(uniques, new HashSet<>(Arrays.asList(starts)).size());
+        clockTraversals(starts, clockRuns);
+    }
+
+    private void clockTraversals(final Integer[] starts, final int clockRuns) {
+        final int times = RANDOM.nextInt(4) + 2;
+        assertTrue(times > 1 && times < 6);
+        final Supplier<Long> original = () -> __.inject(starts).repeat(__.identity()).times(times).<Long>sum().next();
+
+        final TraversalStrategies strategies = new DefaultTraversalStrategies();
+        strategies.addStrategies(RepeatUnrollStrategy.instance());
+        final Supplier<Long> optimized = () -> {
+            final Traversal<Integer, Long> traversal = __.inject(starts).repeat(__.identity()).times(times).sum();
+            traversal.asAdmin().setStrategies(strategies);
+            return traversal.next();
+        };
+
+        final Pair<Double, Long> originalResult;
+        final Pair<Double, Long> optimizedResult;
+        if (RANDOM.nextBoolean()) {
+            originalResult = TimeUtil.clockWithResult(clockRuns, original);
+            optimizedResult = TimeUtil.clockWithResult(clockRuns, optimized);
+        } else {
+            optimizedResult = TimeUtil.clockWithResult(clockRuns, optimized);
+            originalResult = TimeUtil.clockWithResult(clockRuns, original);
+        }
+
+        // System.out.println(originalResult + "---" + optimizedResult);
+        assertEquals(originalResult.getValue1(), optimizedResult.getValue1());
+        assertTrue(originalResult.getValue0() > optimizedResult.getValue0());
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8753366a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProfileTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProfileTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProfileTest.java
index 4d0ce49..548e7ab 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProfileTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProfileTest.java
@@ -33,6 +33,8 @@ import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Profiling;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.ProfileStep;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RepeatUnrollStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ComputerVerificationStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.VerificationException;
 import org.apache.tinkerpop.gremlin.process.traversal.util.Metrics;
 import org.apache.tinkerpop.gremlin.process.traversal.util.MutableMetrics;
@@ -231,7 +233,9 @@ public abstract class ProfileTest extends AbstractGremlinProcessTest {
         printTraversalForm(traversal);
 
         final TraversalMetrics traversalMetrics = traversal.next();
-        validate_g_V_repeat_both_modern_profile(traversalMetrics);
+        validate_g_V_repeat_both_modern_profile(traversalMetrics,
+                traversal.asAdmin().getStrategies().toList().contains(RepeatUnrollStrategy.instance()) &&
+                        !traversal.asAdmin().getStrategies().toList().contains(ComputerVerificationStrategy.instance()));
     }
 
     @Test
@@ -241,10 +245,12 @@ public abstract class ProfileTest extends AbstractGremlinProcessTest {
         printTraversalForm(traversal);
         traversal.iterate();
         final TraversalMetrics traversalMetrics = traversal.asAdmin().getSideEffects().<TraversalMetrics>get(METRICS_KEY);
-        validate_g_V_repeat_both_modern_profile(traversalMetrics);
+        validate_g_V_repeat_both_modern_profile(traversalMetrics,
+                traversal.asAdmin().getStrategies().toList().contains(RepeatUnrollStrategy.instance()) &&
+                        !traversal.asAdmin().getStrategies().toList().contains(ComputerVerificationStrategy.instance()));
     }
 
-    private void validate_g_V_repeat_both_modern_profile(TraversalMetrics traversalMetrics) {
+    private void validate_g_V_repeat_both_modern_profile(TraversalMetrics traversalMetrics, boolean withRepeatUnrollStrategy) {
         traversalMetrics.toString(); // ensure no exceptions are thrown
 
         Metrics metrics = traversalMetrics.getMetrics(0);
@@ -252,25 +258,21 @@ public abstract class ProfileTest extends AbstractGremlinProcessTest {
         assertEquals(6, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue());
 
         metrics = traversalMetrics.getMetrics(1);
-        assertEquals(72, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue());
+        assertEquals(withRepeatUnrollStrategy ? 12 : 72, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue());
         assertNotEquals(0, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
-        assertTrue("Count should be greater than traversers.", metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID) > metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
+        if (!withRepeatUnrollStrategy)
+            assertTrue("Count should be greater than traversers.", metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID) > metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
         assertTrue("Percent duration should be positive.", (Double) metrics.getAnnotation(TraversalMetrics.PERCENT_DURATION_KEY) >= 0);
         assertTrue("Times should be positive.", metrics.getDuration(TimeUnit.MICROSECONDS) >= 0);
 
         // Test the nested global metrics of the repeat step
-        final Metrics vertexStepNestedInRepeat = (Metrics) metrics.getNested().toArray()[0];
-        assertEquals(114, vertexStepNestedInRepeat.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue());
-        assertNotEquals(0, vertexStepNestedInRepeat.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
-        assertTrue("Count should be greater than traversers.", vertexStepNestedInRepeat.getCount(TraversalMetrics.ELEMENT_COUNT_ID) > vertexStepNestedInRepeat.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
-        assertTrue("Times should be positive.", vertexStepNestedInRepeat.getDuration(TimeUnit.MICROSECONDS) >= 0);
-
-        /*final Metrics repeatEndStepNestedInRepeat = (Metrics) metrics.getNested().toArray()[1];
-        assertEquals(72, repeatEndStepNestedInRepeat.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue());
-        assertNotEquals(0, repeatEndStepNestedInRepeat.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
-        assertTrue("Count should be greater than traversers.", repeatEndStepNestedInRepeat.getCount(TraversalMetrics.ELEMENT_COUNT_ID) > repeatEndStepNestedInRepeat.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
-        assertTrue("Times should be positive.", repeatEndStepNestedInRepeat.getDuration(TimeUnit.MICROSECONDS) >= 0);*/
-
+        if (!withRepeatUnrollStrategy) {
+            final Metrics vertexStepNestedInRepeat = (Metrics) metrics.getNested().toArray()[0];
+            assertEquals(114, vertexStepNestedInRepeat.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue());
+            assertNotEquals(0, vertexStepNestedInRepeat.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
+            assertTrue("Count should be greater than traversers.", vertexStepNestedInRepeat.getCount(TraversalMetrics.ELEMENT_COUNT_ID) > vertexStepNestedInRepeat.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
+            assertTrue("Times should be positive.", vertexStepNestedInRepeat.getDuration(TimeUnit.MICROSECONDS) >= 0);
+        }
 
         double totalPercentDuration = 0;
         for (Metrics m : traversalMetrics.getMetrics()) {