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/02/24 21:52:40 UTC

[1/2] incubator-tinkerpop git commit: Okay. So MapReduce in TraversalVertexProgram is going away fast. GroupSideEffectStep and GroupStep are now one step -- GroupStep. Likewise for GroupCountStep. groupCount() is simply groupCount().cap(). This makes the

Repository: incubator-tinkerpop
Updated Branches:
  refs/heads/TINKERPOP-1166 e6adbecfc -> aa79390f7


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStepV3d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStepV3d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStepV3d0.java
deleted file mode 100644
index db10ebd..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStepV3d0.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * 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.step.sideEffect;
-
-import org.apache.commons.configuration.Configuration;
-import org.apache.tinkerpop.gremlin.process.computer.KeyValue;
-import org.apache.tinkerpop.gremlin.process.computer.MapReduce;
-import org.apache.tinkerpop.gremlin.process.computer.traversal.TraversalVertexProgram;
-import org.apache.tinkerpop.gremlin.process.computer.traversal.VertexTraversalSideEffects;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
-import org.apache.tinkerpop.gremlin.process.traversal.step.GraphComputing;
-import org.apache.tinkerpop.gremlin.process.traversal.step.MapReducer;
-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.util.BulkSet;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMatrix;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import org.apache.tinkerpop.gremlin.util.function.HashMapSupplier;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Supplier;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-@Deprecated
-public final class GroupSideEffectStepV3d0<S, K, V, R> extends SideEffectStep<S> implements SideEffectCapable, TraversalParent, ByModulating, GraphComputing, MapReducer<K, Collection<V>, K, R, Map<K, R>> {
-
-    private char state = 'k';
-    private Traversal.Admin<S, K> keyTraversal = null;
-    private Traversal.Admin<S, V> valueTraversal = null;
-    private Traversal.Admin<Collection<V>, R> reduceTraversal = null;
-    private String sideEffectKey;
-    private boolean onGraphComputer = false;
-    private Map<K, Collection<V>> tempGroupByMap;
-
-    public GroupSideEffectStepV3d0(final Traversal.Admin traversal, final String sideEffectKey) {
-        super(traversal);
-        this.sideEffectKey = sideEffectKey;
-        this.traversal.asAdmin().getSideEffects().registerSupplierIfAbsent(this.sideEffectKey, HashMapSupplier.instance());
-    }
-
-    @Override
-    protected void sideEffect(final Traverser.Admin<S> traverser) {
-        final Map<K, Collection<V>> groupMap = null == this.tempGroupByMap ? traverser.sideEffects(this.sideEffectKey) : this.tempGroupByMap; // for nested traversals and not !starts.hasNext()
-        final K key = TraversalUtil.applyNullable(traverser, keyTraversal);
-        final V value = TraversalUtil.applyNullable(traverser, valueTraversal);
-        Collection<V> values = groupMap.get(key);
-        if (null == values) {
-            values = new BulkSet<>();
-            groupMap.put(key, values);
-        }
-        TraversalHelper.addToCollectionUnrollIterator(values, value, traverser.bulk());
-        //////// reducer for OLTP
-        if (!this.onGraphComputer && null != this.reduceTraversal && !this.starts.hasNext()) {
-            this.tempGroupByMap = groupMap;
-            final Map<K, R> reduceMap = new HashMap<>();
-            groupMap.forEach((k, vv) -> reduceMap.put(k, TraversalUtil.applyNullable(vv, this.reduceTraversal)));
-            traverser.sideEffects(this.sideEffectKey, reduceMap);
-        }
-    }
-
-    @Override
-    public String getSideEffectKey() {
-        return this.sideEffectKey;
-    }
-
-    @Override
-    public void onGraphComputer() {
-        this.onGraphComputer = true;
-    }
-
-    @Override
-    public MapReduce<K, Collection<V>, K, R, Map<K, R>> getMapReduce() {
-        return new GroupSideEffectMapReduceV3d0<>(this);
-    }
-
-    @Override
-    public String toString() {
-        return StringFactory.stepString(this, this.sideEffectKey, this.keyTraversal, this.valueTraversal, this.reduceTraversal);
-    }
-
-    @Override
-    public <A, B> List<Traversal.Admin<A, B>> getLocalChildren() {
-        final List<Traversal.Admin<A, B>> children = new ArrayList<>(3);
-        if (null != this.keyTraversal)
-            children.add((Traversal.Admin) this.keyTraversal);
-        if (null != this.valueTraversal)
-            children.add((Traversal.Admin) this.valueTraversal);
-        if (null != this.reduceTraversal)
-            children.add((Traversal.Admin) this.reduceTraversal);
-        return children;
-    }
-
-    public Traversal.Admin<Collection<V>, R> getReduceTraversal() {
-        return this.reduceTraversal;
-    }
-
-    @Override
-    public void modulateBy(final Traversal.Admin<?, ?> kvrTraversal) {
-        if ('k' == this.state) {
-            this.keyTraversal = this.integrateChild(kvrTraversal);
-            this.state = 'v';
-        } else if ('v' == this.state) {
-            this.valueTraversal = this.integrateChild(kvrTraversal);
-            this.state = 'r';
-        } else if ('r' == this.state) {
-            this.reduceTraversal = this.integrateChild(kvrTraversal);
-            this.state = 'x';
-        } else {
-            throw new IllegalStateException("The key, value, and reduce functions for group()-step have already been set");
-        }
-    }
-
-    @Override
-    public Set<TraverserRequirement> getRequirements() {
-        return this.getSelfAndChildRequirements(TraverserRequirement.SIDE_EFFECTS, TraverserRequirement.BULK);
-    }
-
-    @Override
-    public GroupSideEffectStepV3d0<S, K, V, R> clone() {
-        final GroupSideEffectStepV3d0<S, K, V, R> clone = (GroupSideEffectStepV3d0<S, K, V, R>) super.clone();
-        if (null != this.keyTraversal)
-            clone.keyTraversal = clone.integrateChild(this.keyTraversal.clone());
-        if (null != this.valueTraversal)
-            clone.valueTraversal = clone.integrateChild(this.valueTraversal.clone());
-        if (null != this.reduceTraversal)
-            clone.reduceTraversal = clone.integrateChild(this.reduceTraversal.clone());
-        return clone;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = super.hashCode() ^ this.sideEffectKey.hashCode();
-        if (this.keyTraversal != null) result ^= this.keyTraversal.hashCode();
-        if (this.valueTraversal != null) result ^= this.valueTraversal.hashCode();
-        if (this.reduceTraversal != null) result ^= this.reduceTraversal.hashCode();
-        return result;
-    }
-
-    ///////////
-
-    public static final class GroupSideEffectMapReduceV3d0<K, V, R> implements MapReduce<K, Collection<V>, K, R, Map<K, R>> {
-
-        public static final String GROUP_SIDE_EFFECT_STEP_SIDE_EFFECT_KEY = "gremlin.groupSideEffectStep.sideEffectKey";
-        public static final String GROUP_SIDE_EFFECT_STEP_STEP_ID = "gremlin.groupSideEffectStep.stepId";
-
-        private String sideEffectKey;
-        private String groupStepId;
-        private Traversal.Admin<Collection<V>, R> reduceTraversal;
-        private Supplier<Map<K, R>> mapSupplier;
-
-        private GroupSideEffectMapReduceV3d0() {
-
-        }
-
-        public GroupSideEffectMapReduceV3d0(final GroupSideEffectStepV3d0 step) {
-            this.groupStepId = step.getId();
-            this.sideEffectKey = step.getSideEffectKey();
-            this.reduceTraversal = step.getReduceTraversal();
-            this.mapSupplier = step.getTraversal().asAdmin().getSideEffects().<Map<K, R>>getRegisteredSupplier(this.sideEffectKey).orElse(HashMap::new);
-        }
-
-        @Override
-        public void storeState(final Configuration configuration) {
-            MapReduce.super.storeState(configuration);
-            configuration.setProperty(GROUP_SIDE_EFFECT_STEP_SIDE_EFFECT_KEY, this.sideEffectKey);
-            configuration.setProperty(GROUP_SIDE_EFFECT_STEP_STEP_ID, this.groupStepId);
-        }
-
-        @Override
-        public void loadState(final Graph graph, final Configuration configuration) {
-            this.sideEffectKey = configuration.getString(GROUP_SIDE_EFFECT_STEP_SIDE_EFFECT_KEY);
-            this.groupStepId = configuration.getString(GROUP_SIDE_EFFECT_STEP_STEP_ID);
-            final Traversal.Admin<?, ?> traversal = TraversalVertexProgram.getTraversal(graph, configuration);
-            final GroupSideEffectStepV3d0 groupSideEffectStep = new TraversalMatrix<>(traversal).getStepById(this.groupStepId);
-            this.reduceTraversal = groupSideEffectStep.getReduceTraversal();
-            this.mapSupplier = traversal.getSideEffects().<Map<K, R>>getRegisteredSupplier(this.sideEffectKey).orElse(HashMap::new);
-        }
-
-        @Override
-        public boolean doStage(final Stage stage) {
-            return !stage.equals(Stage.COMBINE);
-        }
-
-        @Override
-        public void map(final Vertex vertex, final MapEmitter<K, Collection<V>> emitter) {
-            VertexTraversalSideEffects.of(vertex).<Map<K, Collection<V>>>get(this.sideEffectKey).ifPresent(map -> map.forEach(emitter::emit));
-        }
-
-        @Override
-        public void reduce(final K key, final Iterator<Collection<V>> values, final ReduceEmitter<K, R> emitter) {
-            final Set<V> set = new BulkSet<>();
-            values.forEachRemaining(set::addAll);
-            emitter.emit(key, TraversalUtil.applyNullable(set, this.reduceTraversal));
-        }
-
-        @Override
-        public Map<K, R> generateFinalResult(final Iterator<KeyValue<K, R>> keyValues) {
-            final Map<K, R> map = this.mapSupplier.get();
-            keyValues.forEachRemaining(keyValue -> map.put(keyValue.getKey(), keyValue.getValue()));
-            return map;
-        }
-
-        @Override
-        public String getMemoryKey() {
-            return this.sideEffectKey;
-        }
-
-        @Override
-        public GroupSideEffectMapReduceV3d0<K, V, R> clone() {
-            try {
-                final GroupSideEffectMapReduceV3d0<K, V, R> clone = (GroupSideEffectMapReduceV3d0<K, V, R>) super.clone();
-                if (null != clone.reduceTraversal)
-                    clone.reduceTraversal = this.reduceTraversal.clone();
-                return clone;
-            } catch (final CloneNotSupportedException e) {
-                throw new IllegalStateException(e.getMessage(), e);
-            }
-        }
-
-        @Override
-        public String toString() {
-            return StringFactory.mapReduceString(this, this.getMemoryKey());
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupStep.java
new file mode 100644
index 0000000..845591a
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupStep.java
@@ -0,0 +1,240 @@
+/*
+ * 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.step.sideEffect;
+
+import org.apache.tinkerpop.gremlin.process.computer.MemoryComputeKey;
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.ElementValueTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.FunctionTraverser;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.IdentityTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.TokenTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Barrier;
+import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GraphComputing;
+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.map.LambdaMapStep;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
+import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+import org.apache.tinkerpop.gremlin.util.function.HashMapSupplier;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.BinaryOperator;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class GroupStep<S, K, V> extends SideEffectStep<S> implements SideEffectCapable, TraversalParent, ByModulating, GraphComputing {
+
+    private char state = 'k';
+    private Traversal.Admin<S, K> keyTraversal = null;
+    private Traversal.Admin<S, ?> valueTraversal = this.integrateChild(__.identity().asAdmin());   // used in OLAP
+    private Traversal.Admin<?, V> reduceTraversal = this.integrateChild(__.fold().asAdmin());      // used in OLAP
+    private Traversal.Admin<S, V> valueReduceTraversal = this.integrateChild(__.fold().asAdmin()); // used in OLTP
+    ///
+    private String sideEffectKey;
+    private boolean onGraphComputer = false;
+
+    public GroupStep(final Traversal.Admin traversal, final String sideEffectKey) {
+        super(traversal);
+        this.sideEffectKey = sideEffectKey;
+        this.traversal.asAdmin().getSideEffects().registerSupplierIfAbsent(this.sideEffectKey, HashMapSupplier.instance());
+    }
+
+    @Override
+    public void modulateBy(final Traversal.Admin<?, ?> kvTraversal) {
+        if ('k' == this.state) {
+            this.keyTraversal = this.integrateChild(kvTraversal);
+            this.state = 'v';
+        } else if ('v' == this.state) {
+            this.valueReduceTraversal = this.integrateChild(GroupStep.convertValueTraversal(kvTraversal));
+            final List<Traversal.Admin<?, ?>> splitTraversal = GroupStep.splitOnBarrierStep(this.valueReduceTraversal);
+            this.valueTraversal = this.integrateChild(splitTraversal.get(0));
+            this.reduceTraversal = this.integrateChild(splitTraversal.get(1));
+            this.state = 'x';
+        } else {
+            throw new IllegalStateException("The key and value traversals for group()-step have already been set: " + this);
+        }
+    }
+
+    @Override
+    public Optional<MemoryComputeKey> getMemoryComputeKey() {
+        return Optional.of(MemoryComputeKey.of(this.getSideEffectKey(), GroupBiOperator.INSTANCE, false, false));
+    }
+
+    @Override
+    protected void sideEffect(final Traverser.Admin<S> traverser) {
+        Map<K, Object> map = traverser.sideEffects(this.sideEffectKey);
+        final K key = TraversalUtil.applyNullable(traverser, this.keyTraversal);
+        final TraverserSet<Object> traverserSet = new TraverserSet<>();
+        if (this.onGraphComputer) {
+            this.valueTraversal.reset();
+            this.valueTraversal.addStart(traverser);
+            this.valueTraversal.getEndStep().forEachRemaining(t -> traverserSet.add((Traverser.Admin) t.asAdmin()));
+            final TraverserSet<Object> set = (TraverserSet) map.get(key);
+            if (null == set)
+                map.put(key, traverserSet);
+            else
+                set.addAll(traverserSet);
+        } else {
+            traverserSet.add((Traverser.Admin) traverser.split());
+            Traversal.Admin valueReduceTraversal = (Traversal.Admin) map.get(key);
+            if (null == valueReduceTraversal) {
+                valueReduceTraversal = this.valueReduceTraversal.clone();
+                map.put(key, valueReduceTraversal);
+            }
+            traverserSet.forEach(valueReduceTraversal::addStart);
+            // TODO: TraversalHelper.getFirstStepOfAssignableClass(Barrier.class, valueReduceTraversal).ifPresent(Barrier::processAllStarts);
+        }
+    }
+
+    @Override
+    public String getSideEffectKey() {
+        return this.sideEffectKey;
+    }
+
+    @Override
+    public void onGraphComputer() {
+        this.onGraphComputer = true;
+    }
+
+    @Override
+    public String toString() {
+        return StringFactory.stepString(this, this.sideEffectKey, this.keyTraversal, this.valueReduceTraversal);
+    }
+
+    @Override
+    public List<Traversal.Admin<?, ?>> getLocalChildren() {
+        final List<Traversal.Admin<?, ?>> children = new ArrayList<>(4);
+        if (null != this.keyTraversal)
+            children.add((Traversal.Admin) this.keyTraversal);
+        children.add(this.valueReduceTraversal);
+        children.add(this.valueTraversal);
+        children.add(this.reduceTraversal);
+        return children;
+    }
+
+    @Override
+    public Set<TraverserRequirement> getRequirements() {
+        return this.getSelfAndChildRequirements(TraverserRequirement.OBJECT, TraverserRequirement.BULK, TraverserRequirement.SIDE_EFFECTS);
+    }
+
+    @Override
+    public GroupStep<S, K, V> clone() {
+        final GroupStep<S, K, V> clone = (GroupStep<S, K, V>) super.clone();
+        if (null != this.keyTraversal)
+            clone.keyTraversal = clone.integrateChild(this.keyTraversal.clone());
+        clone.valueReduceTraversal = clone.integrateChild(this.valueReduceTraversal.clone());
+        clone.valueTraversal = clone.integrateChild(this.valueTraversal.clone());
+        clone.reduceTraversal = clone.integrateChild(this.reduceTraversal.clone());
+        return clone;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode() ^ this.sideEffectKey.hashCode();
+        if (this.keyTraversal != null) result ^= this.keyTraversal.hashCode();
+        result ^= this.valueReduceTraversal.hashCode();
+        return result;
+    }
+
+    @Override
+    public Object generateFinalResult(final Object object) {
+        final Map<K, Object> map = (Map<K, Object>) object;
+        final Map<K, Object> reducedMap = new HashMap<>();
+        if (this.onGraphComputer) {
+            for (final K key : map.keySet()) {
+                final Traversal.Admin<?, V> reduceClone = this.reduceTraversal.clone();
+                reduceClone.addStarts(((TraverserSet) map.get(key)).iterator());
+                reducedMap.put(key, reduceClone.next());
+            }
+        } else
+            map.forEach((key, traversal) -> reducedMap.put(key, ((Traversal.Admin) traversal).next()));
+        return reducedMap;
+    }
+
+    /////////////////////////////
+
+    private static <S, E> Traversal.Admin<S, E> convertValueTraversal(final Traversal.Admin<S, E> valueReduceTraversal) {
+        if (valueReduceTraversal instanceof ElementValueTraversal ||
+                valueReduceTraversal instanceof TokenTraversal ||
+                valueReduceTraversal instanceof IdentityTraversal ||
+                valueReduceTraversal.getStartStep() instanceof LambdaMapStep && ((LambdaMapStep) valueReduceTraversal.getStartStep()).getMapFunction() instanceof FunctionTraverser) {
+            return (Traversal.Admin<S, E>) __.map(valueReduceTraversal).fold();
+        } else {
+            return valueReduceTraversal;
+        }
+    }
+
+    private static List<Traversal.Admin<?, ?>> splitOnBarrierStep(final Traversal.Admin<?, ?> valueReduceTraversal) {
+        if (TraversalHelper.getFirstStepOfAssignableClass(Barrier.class, valueReduceTraversal).isPresent()) {
+            final Traversal.Admin<?, ?> first = __.identity().asAdmin();
+            final Traversal.Admin<?, ?> second = __.identity().asAdmin();
+            boolean onSecond = false;
+            for (final Step step : valueReduceTraversal.getSteps()) {
+                if (step instanceof Barrier)
+                    onSecond = true;
+                if (onSecond)
+                    second.addStep(step.clone());
+                else
+                    first.addStep(step.clone());
+            }
+            return Arrays.asList(first, second);
+        } else {
+            return Arrays.asList(valueReduceTraversal.clone(), __.identity().asAdmin());
+        }
+    }
+
+    /////////////////////////////
+
+    public static final class GroupBiOperator<K, V> implements BinaryOperator<Map<K, V>>, Serializable {
+
+        private static final GroupBiOperator INSTANCE = new GroupBiOperator();
+
+        private GroupBiOperator() {
+
+        }
+
+        @Override
+        public Map<K, V> apply(final Map<K, V> mutatingSeed, final Map<K, V> map) {
+            for (final K key : map.keySet()) {
+                TraverserSet traverserSet = (TraverserSet) mutatingSeed.get(key);
+                if (null == traverserSet) {
+                    traverserSet = new TraverserSet<>();
+                    mutatingSeed.put(key, (V) traverserSet);
+                }
+                traverserSet.addAll((TraverserSet) map.get(key));
+            }
+            return mutatingSeed;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupStepV3d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupStepV3d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupStepV3d0.java
new file mode 100644
index 0000000..edc571b
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupStepV3d0.java
@@ -0,0 +1,182 @@
+/*
+ * 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.step.sideEffect;
+
+import org.apache.tinkerpop.gremlin.process.computer.MemoryComputeKey;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GraphComputing;
+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.util.BulkSet;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
+import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+import org.apache.tinkerpop.gremlin.util.function.HashMapSupplier;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.BinaryOperator;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+@Deprecated
+public final class GroupStepV3d0<S, K, V, R> extends SideEffectStep<S> implements SideEffectCapable, TraversalParent, ByModulating, GraphComputing {
+
+    private char state = 'k';
+    private Traversal.Admin<S, K> keyTraversal = null;
+    private Traversal.Admin<S, V> valueTraversal = null;
+    private Traversal.Admin<Collection<V>, R> reduceTraversal = null;
+    private String sideEffectKey;
+
+    public GroupStepV3d0(final Traversal.Admin traversal, final String sideEffectKey) {
+        super(traversal);
+        this.sideEffectKey = sideEffectKey;
+        this.traversal.asAdmin().getSideEffects().registerSupplierIfAbsent(this.sideEffectKey, HashMapSupplier.instance());
+    }
+
+    @Override
+    public Optional<MemoryComputeKey> getMemoryComputeKey() {
+        return Optional.of(MemoryComputeKey.of(this.getSideEffectKey(), GroupBiOperatorV3d0.INSTANCE, false, false));
+    }
+
+    @Override
+    protected void sideEffect(final Traverser.Admin<S> traverser) {
+        final Map<K, Collection<V>> groupMap = traverser.sideEffects(this.sideEffectKey);
+        final K key = TraversalUtil.applyNullable(traverser, keyTraversal);
+        final V value = TraversalUtil.applyNullable(traverser, valueTraversal);
+        Collection<V> values = groupMap.get(key);
+        if (null == values) {
+            values = new BulkSet<>();
+            groupMap.put(key, values);
+        }
+        TraversalHelper.addToCollectionUnrollIterator(values, value, traverser.bulk());
+    }
+
+    @Override
+    public String getSideEffectKey() {
+        return this.sideEffectKey;
+    }
+
+    @Override
+    public void onGraphComputer() {
+    }
+
+    @Override
+    public String toString() {
+        return StringFactory.stepString(this, this.sideEffectKey, this.keyTraversal, this.valueTraversal, this.reduceTraversal);
+    }
+
+    @Override
+    public Map<K, R> generateFinalResult(final Object valueMap) {
+        final Map<K, R> reducedMap = new HashMap<>();
+        for (final K key : ((Map<K, Collection<V>>) valueMap).keySet()) {
+            final R r = TraversalUtil.applyNullable(((Map<K, Collection<V>>) valueMap).get(key), this.reduceTraversal);
+            reducedMap.put(key, r);
+        }
+        return reducedMap;
+    }
+
+    @Override
+    public <A, B> List<Traversal.Admin<A, B>> getLocalChildren() {
+        final List<Traversal.Admin<A, B>> children = new ArrayList<>(3);
+        if (null != this.keyTraversal)
+            children.add((Traversal.Admin) this.keyTraversal);
+        if (null != this.valueTraversal)
+            children.add((Traversal.Admin) this.valueTraversal);
+        if (null != this.reduceTraversal)
+            children.add((Traversal.Admin) this.reduceTraversal);
+        return children;
+    }
+
+    @Override
+    public void modulateBy(final Traversal.Admin<?, ?> kvrTraversal) {
+        if ('k' == this.state) {
+            this.keyTraversal = this.integrateChild(kvrTraversal);
+            this.state = 'v';
+        } else if ('v' == this.state) {
+            this.valueTraversal = this.integrateChild(kvrTraversal);
+            this.state = 'r';
+        } else if ('r' == this.state) {
+            this.reduceTraversal = this.integrateChild(kvrTraversal);
+            this.state = 'x';
+        } else {
+            throw new IllegalStateException("The key, value, and reduce functions for group()-step have already been set");
+        }
+    }
+
+    @Override
+    public Set<TraverserRequirement> getRequirements() {
+        return this.getSelfAndChildRequirements(TraverserRequirement.SIDE_EFFECTS, TraverserRequirement.BULK);
+    }
+
+    @Override
+    public GroupStepV3d0<S, K, V, R> clone() {
+        final GroupStepV3d0<S, K, V, R> clone = (GroupStepV3d0<S, K, V, R>) super.clone();
+        if (null != this.keyTraversal)
+            clone.keyTraversal = clone.integrateChild(this.keyTraversal.clone());
+        if (null != this.valueTraversal)
+            clone.valueTraversal = clone.integrateChild(this.valueTraversal.clone());
+        if (null != this.reduceTraversal)
+            clone.reduceTraversal = clone.integrateChild(this.reduceTraversal.clone());
+        return clone;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode() ^ this.sideEffectKey.hashCode();
+        if (this.keyTraversal != null) result ^= this.keyTraversal.hashCode();
+        if (this.valueTraversal != null) result ^= this.valueTraversal.hashCode();
+        if (this.reduceTraversal != null) result ^= this.reduceTraversal.hashCode();
+        return result;
+    }
+
+    //////////
+
+    @Deprecated
+    public static class GroupBiOperatorV3d0<K, V> implements BinaryOperator<Map<K, V>>, Serializable {
+
+        private final static GroupBiOperatorV3d0 INSTANCE = new GroupBiOperatorV3d0();
+
+        @Override
+        public Map<K, V> apply(final Map<K, V> mutatingSeed, final Map<K, V> map) {
+            for (final K key : map.keySet()) {
+                final BulkSet<V> values = (BulkSet<V>) map.get(key);
+                BulkSet<V> seedValues = (BulkSet<V>) mutatingSeed.get(key);
+                if (null == seedValues) {
+                    seedValues = new BulkSet<>();
+                    mutatingSeed.put(key, (V) seedValues);
+                }
+                seedValues.addAll(values);
+            }
+            return mutatingSeed;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SideEffectCapStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SideEffectCapStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SideEffectCapStep.java
index a784bfd..74a1e42 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SideEffectCapStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SideEffectCapStep.java
@@ -19,9 +19,12 @@
 package org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect;
 
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GraphComputing;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.SupplyingBarrierStep;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.FinalGet;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
 import java.util.ArrayList;
@@ -34,9 +37,11 @@ import java.util.Set;
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class SideEffectCapStep<S, E> extends SupplyingBarrierStep<S, E> {
+public final class SideEffectCapStep<S, E> extends SupplyingBarrierStep<S, E> implements ByModulating, GraphComputing {
 
     private List<String> sideEffectKeys;
+    private transient Map<String, GraphComputing> sideEffectFinalizer;
+    private boolean onGraphComputer = false;
 
     public SideEffectCapStep(final Traversal.Admin traversal, final String sideEffectKey, final String... sideEffectKeys) {
         super(traversal);
@@ -71,17 +76,52 @@ public final class SideEffectCapStep<S, E> extends SupplyingBarrierStep<S, E> {
     }
 
     @Override
+    public Traverser<E> processNextStart() {
+        if (null == this.sideEffectFinalizer) {  // and NOT onGraphComputer
+            this.sideEffectFinalizer = new HashMap<>();
+            for (final String key : this.sideEffectKeys) {
+                for (final GraphComputing graphComputing : TraversalHelper.getStepsOfAssignableClassRecursively(GraphComputing.class, TraversalHelper.getRootTraversal(this.getTraversal()))) {
+                    if (graphComputing.getMemoryComputeKey().isPresent() && graphComputing.getMemoryComputeKey().get().getKey().equals(key)) {
+                        this.sideEffectFinalizer.put(key, graphComputing);
+                    }
+                }
+            }
+        }
+        return super.processNextStart();
+    }
+
+    @Override
     protected E supply() {
-        return this.sideEffectKeys.size() == 1 ?
-                FinalGet.tryFinalGet(this.getTraversal().asAdmin().getSideEffects().<E>get(this.sideEffectKeys.get(0)).get()) :
-                (E) this.getMapOfSideEffects();
+        if (this.sideEffectKeys.size() == 1) {
+            final String sideEffectKey = this.sideEffectKeys.get(0);
+            final E result = this.getTraversal().getSideEffects().<E>get(sideEffectKey).get();
+            if (!this.onGraphComputer && sideEffectKey.endsWith("destroy"))
+                this.getTraversal().getSideEffects().set(sideEffectKey, this.getTraversal().getSideEffects().getRegisteredSupplier(sideEffectKey).get().get());
+            final GraphComputing finalizer = this.sideEffectFinalizer.get(sideEffectKey);
+            return (this.onGraphComputer || null == finalizer) ? result : (E) finalizer.generateFinalResult(result);
+        } else
+            return (E) this.getMapOfSideEffects();
     }
 
     public Map<String, Object> getMapOfSideEffects() {
         final Map<String, Object> sideEffects = new HashMap<>();
         for (final String sideEffectKey : this.sideEffectKeys) {
-            this.getTraversal().asAdmin().getSideEffects().get(sideEffectKey).ifPresent(value -> sideEffects.put(sideEffectKey, FinalGet.tryFinalGet(value)));
+            this.getTraversal().asAdmin().getSideEffects().get(sideEffectKey).ifPresent(value -> {
+                final GraphComputing finalizer = this.sideEffectFinalizer.get(sideEffectKey);
+                sideEffects.put(sideEffectKey, (null == finalizer || this.onGraphComputer) ? value : finalizer.generateFinalResult(value));
+            });
         }
         return sideEffects;
     }
+
+    // TODO: either expand or make this a strategy
+    @Override
+    public void modulateBy(final Traversal.Admin<?, ?> traversal) throws UnsupportedOperationException {
+        ((ByModulating) this.getPreviousStep()).modulateBy(traversal);
+    }
+
+    @Override
+    public void onGraphComputer() {
+        this.onGraphComputer = true;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/GroupStepHelper.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/GroupStepHelper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/GroupStepHelper.java
deleted file mode 100644
index ab47ff4..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/GroupStepHelper.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.step.util;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Step;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.ElementValueTraversal;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.FunctionTraverser;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.IdentityTraversal;
-import org.apache.tinkerpop.gremlin.process.traversal.lambda.TokenTraversal;
-import org.apache.tinkerpop.gremlin.process.traversal.step.Barrier;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.LambdaMapStep;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class GroupStepHelper {
-
-    private GroupStepHelper() {
-
-    }
-
-    public static <S, E> Traversal.Admin<S, E> convertValueTraversal(final Traversal.Admin<S, E> valueReduceTraversal) {
-        if (valueReduceTraversal instanceof ElementValueTraversal ||
-                valueReduceTraversal instanceof TokenTraversal ||
-                valueReduceTraversal instanceof IdentityTraversal ||
-                valueReduceTraversal.getStartStep() instanceof LambdaMapStep && ((LambdaMapStep) valueReduceTraversal.getStartStep()).getMapFunction() instanceof FunctionTraverser) {
-            return (Traversal.Admin<S, E>) __.map(valueReduceTraversal).fold();
-        } else {
-            return valueReduceTraversal;
-        }
-    }
-
-    public static List<Traversal.Admin<?, ?>> splitOnBarrierStep(final Traversal.Admin<?, ?> valueReduceTraversal) {
-        if (TraversalHelper.getFirstStepOfAssignableClass(Barrier.class, valueReduceTraversal).isPresent()) {
-            final Traversal.Admin<?, ?> first = __.identity().asAdmin();
-            final Traversal.Admin<?, ?> second = __.identity().asAdmin();
-            boolean onSecond = false;
-            for (final Step step : valueReduceTraversal.getSteps()) {
-                if (step instanceof Barrier)
-                    onSecond = true;
-                if (onSecond)
-                    second.addStep(step.clone());
-                else
-                    first.addStep(step.clone());
-            }
-            return Arrays.asList(first, second);
-        } else {
-            return Arrays.asList(valueReduceTraversal.clone(), __.identity().asAdmin());
-        }
-    }
-
-
-    /////////
-
-    public static class GroupMap<S, K, V> extends HashMap<K, Traversal.Admin<S, V>> implements FinalGet<Map<K, V>> {
-
-        private final Map<K, V> map;
-
-        public GroupMap(final Map<K, V> map) {
-            this.map = map;
-        }
-
-        @Override
-        public Map<K, V> getFinal() {
-            this.forEach((key, traversal) -> this.map.put(key, traversal.next()));
-            return this.map;
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ReducingBarrierStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ReducingBarrierStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ReducingBarrierStep.java
index c73f083..b147092 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ReducingBarrierStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/ReducingBarrierStep.java
@@ -94,17 +94,13 @@ public abstract class ReducingBarrierStep<S, E> extends AbstractStep<S, E> imple
             this.seed = this.reducingBiOperator.apply(this.seed, this.projectTraverser(this.starts.next()));
     }
 
-    public E generateFinalReduction(final Object reduction) {
-        return (E) reduction;
-    }
-
     @Override
     public Traverser<E> processNextStart() {
         if (this.done)
             throw FastNoSuchElementException.instance();
         this.processAllStarts();
         this.done = true;
-        final Traverser<E> traverser = TraversalHelper.getRootTraversal(this.getTraversal()).getTraverserGenerator().generate(this.onGraphComputer ? this.seed : this.generateFinalReduction(this.seed), (Step) this, 1l);
+        final Traverser<E> traverser = TraversalHelper.getRootTraversal(this.getTraversal()).getTraverserGenerator().generate(this.onGraphComputer ? this.seed : FinalGet.tryFinalGet(this.seed), (Step) this, 1l);
         this.seed = null;
         return traverser;
     }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/SupplyingBarrierStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/SupplyingBarrierStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/SupplyingBarrierStep.java
index f898c34..4f56fed 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/SupplyingBarrierStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/util/SupplyingBarrierStep.java
@@ -24,6 +24,8 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Barrier;
 import org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementException;
 
+import java.util.Iterator;
+
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
@@ -38,6 +40,19 @@ public abstract class SupplyingBarrierStep<S, E> extends AbstractStep<S, E> impl
     protected abstract E supply();
 
     @Override
+    public void addStarts(final Iterator<Traverser<S>> starts) {
+        if (starts.hasNext())
+            this.done = false;
+        super.addStarts(starts);
+    }
+
+    @Override
+    public void addStart(final Traverser<S> start) {
+        this.done = false;
+        super.addStart(start);
+    }
+
+    @Override
     public void reset() {
         super.reset();
         this.done = false;

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java
index 05cd15e..640898e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java
@@ -26,14 +26,14 @@ import org.apache.tinkerpop.gremlin.process.traversal.Operator;
 import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.CountGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.FoldStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupCountStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupStepV3d0;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MaxGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MeanGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MinGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.SumGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.TreeStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupStepV3d0;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_LP_O_P_S_SE_SL_Traverser;

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStepTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStepTest.java
deleted file mode 100644
index 7e68291..0000000
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStepTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.step.map;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * @author Daniel Kuppitz (http://gremlin.guru)
- */
-public class GroupCountStepTest extends StepTest {
-
-    @Override
-    protected List<Traversal> getTraversals() {
-        return Arrays.asList(
-                __.groupCount(),
-                __.groupCount().by("name"),
-                __.groupCount().by("age")
-        );
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStepTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStepTest.java
deleted file mode 100644
index 73a434c..0000000
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStepTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.step.map;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Scope;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
-import org.apache.tinkerpop.gremlin.structure.T;
-
-import java.util.Arrays;
-import java.util.List;
-
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.count;
-
-/**
- * @author Daniel Kuppitz (http://gremlin.guru)
- */
-public class GroupStepTest extends StepTest {
-
-    @Override
-    protected List<Traversal> getTraversals() {
-        return Arrays.asList(
-                __.group().by(T.label),
-                __.group().by(T.label).by("name"),
-                __.group().by(T.label).by(__.values("name").count())
-        );
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStepV3d0Test.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStepV3d0Test.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStepV3d0Test.java
deleted file mode 100644
index 2ba2714..0000000
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStepV3d0Test.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.step.map;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Scope;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
-import org.apache.tinkerpop.gremlin.structure.T;
-
-import java.util.Arrays;
-import java.util.List;
-
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.count;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-@Deprecated
-public class GroupStepV3d0Test extends StepTest {
-
-    @Override
-    protected List<Traversal> getTraversals() {
-        return Arrays.asList(
-                __.groupV3d0().by(T.label),
-                __.groupV3d0().by(T.label).by("name"),
-                __.groupV3d0().by(T.label).by("name").by(count(Scope.local))
-        );
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountSideEffectStepTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountSideEffectStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountSideEffectStepTest.java
deleted file mode 100644
index a43e9b8..0000000
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountSideEffectStepTest.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.step.sideEffect;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * @author Daniel Kuppitz (http://gremlin.guru)
- */
-public class GroupCountSideEffectStepTest extends StepTest {
-
-    @Override
-    protected List<Traversal> getTraversals() {
-        return Arrays.asList(
-                __.groupCount("x"),
-                __.groupCount("x").by("name"),
-                __.groupCount("x").by("age"),
-                __.groupCount("y"),
-                __.groupCount("y").by("name"),
-                __.groupCount("y").by("age")
-        );
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountStepTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountStepTest.java
new file mode 100644
index 0000000..273bf02
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountStepTest.java
@@ -0,0 +1,47 @@
+/*
+ * 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.step.sideEffect;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+public class GroupCountStepTest extends StepTest {
+
+    @Override
+    protected List<Traversal> getTraversals() {
+        return Arrays.asList(
+                __.groupCount("x"),
+                __.groupCount("x").by("name"),
+                __.groupCount("x").by("age"),
+                __.groupCount("y"),
+                __.groupCount("y").by("name"),
+                __.groupCount("y").by("age"),
+                __.groupCount(),
+                __.groupCount().by("name"),
+                __.groupCount().by("age")
+        );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStepTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStepTest.java
deleted file mode 100644
index 6e92cb2..0000000
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStepTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.step.sideEffect;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
-import org.apache.tinkerpop.gremlin.structure.T;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * @author Daniel Kuppitz (http://gremlin.guru)
- */
-public class GroupSideEffectStepTest extends StepTest {
-
-    @Override
-    protected List<Traversal> getTraversals() {
-        return Arrays.asList(
-                __.group("x").by(T.label),
-                __.group("x").by(T.label).by("name"),
-                __.group("x").by(T.label).by(__.values("name").count()),
-                __.group("y").by(T.label),
-                __.group("y").by(T.label).by("name"),
-                __.group("y").by(T.label).by(__.values("name").count())
-        );
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStepV3d0Test.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStepV3d0Test.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStepV3d0Test.java
deleted file mode 100644
index 92b6923..0000000
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStepV3d0Test.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.step.sideEffect;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-@Deprecated
-public class GroupSideEffectStepV3d0Test extends StepTest {
-
-    @Override
-    protected List<Traversal> getTraversals() {
-        return Arrays.asList(
-                __.groupCount("x"),
-                __.groupCount("x").by("name"),
-                __.groupCount("x").by("age"),
-                __.groupCount("y"),
-                __.groupCount("y").by("name"),
-                __.groupCount("y").by("age")
-        );
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupStepTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupStepTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupStepTest.java
new file mode 100644
index 0000000..f2f6fc5
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupStepTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.step.sideEffect;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
+import org.apache.tinkerpop.gremlin.structure.T;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ */
+public class GroupStepTest extends StepTest {
+
+    @Override
+    protected List<Traversal> getTraversals() {
+        return Arrays.asList(
+                __.group("x").by(T.label),
+                __.group("x").by(T.label).by("name"),
+                __.group("x").by(T.label).by(__.values("name").count()),
+                __.group("y").by(T.label),
+                __.group("y").by(T.label).by("name"),
+                __.group("y").by(T.label).by(__.values("name").count()),
+                __.group().by(T.label),
+                __.group().by(T.label).by("name"),
+                __.group().by(T.label).by(__.values("name").count())
+        );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupStepV3D0Test.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupStepV3D0Test.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupStepV3D0Test.java
new file mode 100644
index 0000000..4230b4f
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupStepV3D0Test.java
@@ -0,0 +1,47 @@
+/*
+ * 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.step.sideEffect;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Scope;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
+import org.apache.tinkerpop.gremlin.structure.T;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.count;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+@Deprecated
+public class GroupStepV3d0Test extends StepTest {
+
+    @Override
+    protected List<Traversal> getTraversals() {
+        return Arrays.asList(
+                __.groupV3d0().by(T.label),
+                __.groupV3d0().by(T.label).by("name"),
+                __.groupV3d0().by(T.label).by("name").by(count(Scope.local))
+        );
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java
index 10974ba..857057b 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java
@@ -21,13 +21,16 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.map;
 import org.apache.tinkerpop.gremlin.LoadGraphWith;
 import org.apache.tinkerpop.gremlin.process.AbstractGremlinProcessTest;
 import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner;
+import org.apache.tinkerpop.gremlin.process.IgnoreEngine;
 import org.apache.tinkerpop.gremlin.process.traversal.Order;
 import org.apache.tinkerpop.gremlin.process.traversal.Pop;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalEngine;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -277,6 +280,7 @@ public abstract class SelectTest extends AbstractGremlinProcessTest {
     }
 
     @Test
+    @IgnoreEngine(TraversalEngine.Type.COMPUTER)
     @LoadGraphWith(MODERN)
     public void g_V_hasLabelXpersonX_asXpX_mapXbothE_label_groupCountX_asXrX_selectXp_rX() {
         final Traversal<Vertex, Map<String, Object>> traversal = get_g_V_hasLabelXpersonX_asXpX_mapXbothE_label_groupCountX_asXrX_selectXp_rX();


[2/2] incubator-tinkerpop git commit: Okay. So MapReduce in TraversalVertexProgram is going away fast. GroupSideEffectStep and GroupStep are now one step -- GroupStep. Likewise for GroupCountStep. groupCount() is simply groupCount().cap(). This makes the

Posted by ok...@apache.org.
Okay. So MapReduce in TraversalVertexProgram is going away fast. GroupSideEffectStep and GroupStep are now one step -- GroupStep. Likewise for GroupCountStep. groupCount() is simply groupCount().cap(). This makes the code alot simpler and easier to optimize everything in one spot. With this direction, TraversalVertexProgram will be able to do OLAP ... then in terminate(), do reductions. If those reductions yield traversers, termiate() == false, and we distributed messages again. Thus, we will have OLTP->OLAP->OLTP->OLAP all possible within in a single TraveraslVertexProgram. The idea is that the master worker (termiante()) will do OLTP processing until it needs to go back to OLAP (if necessary). There is still lots more work to do. This push is to save work.


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

Branch: refs/heads/TINKERPOP-1166
Commit: aa79390f7afd78091755784753ed67a311f1d7da
Parents: e6adbec
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Wed Feb 24 13:52:29 2016 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Wed Feb 24 13:52:29 2016 -0700

----------------------------------------------------------------------
 .../traversal/TraversalVertexProgram.java       |  23 +-
 .../traversal/dsl/graph/GraphTraversal.java     |  25 +-
 .../process/traversal/step/GraphComputing.java  |  11 +
 .../traversal/step/map/CountGlobalStep.java     |  11 +-
 .../process/traversal/step/map/FoldStep.java    |  13 +-
 .../traversal/step/map/GroupCountStep.java      | 104 -------
 .../process/traversal/step/map/GroupStep.java   | 193 -------------
 .../traversal/step/map/GroupStepV3d0.java       | 162 -----------
 .../traversal/step/map/MaxGlobalStep.java       |  12 +-
 .../traversal/step/map/MeanGlobalStep.java      |  15 +-
 .../traversal/step/map/MinGlobalStep.java       |  12 +-
 .../traversal/step/map/SumGlobalStep.java       |  11 +-
 .../process/traversal/step/map/TreeStep.java    |  11 +-
 .../sideEffect/GroupCountSideEffectStep.java    | 185 -------------
 .../step/sideEffect/GroupCountStep.java         | 134 +++++++++
 .../step/sideEffect/GroupSideEffectStep.java    | 272 -------------------
 .../sideEffect/GroupSideEffectStepV3d0.java     | 257 ------------------
 .../traversal/step/sideEffect/GroupStep.java    | 240 ++++++++++++++++
 .../step/sideEffect/GroupStepV3d0.java          | 182 +++++++++++++
 .../step/sideEffect/SideEffectCapStep.java      |  52 +++-
 .../traversal/step/util/GroupStepHelper.java    |  95 -------
 .../step/util/ReducingBarrierStep.java          |   6 +-
 .../step/util/SupplyingBarrierStep.java         |  15 +
 .../gremlin/structure/io/gryo/GryoMapper.java   |   6 +-
 .../traversal/step/map/GroupCountStepTest.java  |  41 ---
 .../traversal/step/map/GroupStepTest.java       |  45 ---
 .../traversal/step/map/GroupStepV3d0Test.java   |  47 ----
 .../GroupCountSideEffectStepTest.java           |  44 ---
 .../step/sideEffect/GroupCountStepTest.java     |  47 ++++
 .../sideEffect/GroupSideEffectStepTest.java     |  45 ---
 .../sideEffect/GroupSideEffectStepV3d0Test.java |  46 ----
 .../step/sideEffect/GroupStepTest.java          |  48 ++++
 .../step/sideEffect/GroupStepV3D0Test.java      |  47 ++++
 .../process/traversal/step/map/SelectTest.java  |   4 +
 34 files changed, 885 insertions(+), 1576 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraversalVertexProgram.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraversalVertexProgram.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraversalVertexProgram.java
index 6580600..a6fa0fd 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraversalVertexProgram.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraversalVertexProgram.java
@@ -34,6 +34,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSideEffects;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GraphComputing;
 import org.apache.tinkerpop.gremlin.process.traversal.step.MapReducer;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffectCapStep;
@@ -57,6 +58,7 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 
@@ -81,6 +83,7 @@ public final class TraversalVertexProgram implements VertexProgram<TraverserSet<
     // TODO: if not an adjacent traversal, use Local message scope -- a dual messaging system.
     private static final Set<MessageScope> MESSAGE_SCOPES = new HashSet<>(Collections.singletonList(MessageScope.Global.instance()));
     private Set<MemoryComputeKey> memoryComputeKeys = new HashSet<>();
+    private Set<String> sideEffectKeys = new HashSet<>();
     private static final Set<VertexComputeKey> VERTEX_COMPUTE_KEYS = new HashSet<>(Arrays.asList(
             VertexComputeKey.of(HALTED_TRAVERSERS, false),
             VertexComputeKey.of(TraversalSideEffects.SIDE_EFFECTS, false)));
@@ -120,8 +123,9 @@ public final class TraversalVertexProgram implements VertexProgram<TraverserSet<
             this.mapReducers.add(new TraverserMapReduce(this.traversal.get()));
             this.memoryComputeKeys.add(MemoryComputeKey.of(TraverserMapReduce.TRAVERSERS, MemoryComputeKey.setOperator(), false, false));
         }
-        for (final ReducingBarrierStep<?, ?> reducingBarrierStep : TraversalHelper.getStepsOfAssignableClassRecursively(ReducingBarrierStep.class, this.traversal.get())) {
-            this.memoryComputeKeys.add(MemoryComputeKey.of(ReducingBarrierStep.REDUCING, reducingBarrierStep.getBiOperator(), false, false));
+        for (final GraphComputing graphComputing : TraversalHelper.getStepsOfAssignableClassRecursively(GraphComputing.class, this.traversal.get())) {
+            graphComputing.getMemoryComputeKey().ifPresent(this.memoryComputeKeys::add);
+            graphComputing.getMemoryComputeKey().ifPresent(x -> this.sideEffectKeys.add(x.getKey()));
         }
     }
 
@@ -177,15 +181,24 @@ public final class TraversalVertexProgram implements VertexProgram<TraverserSet<
         } else {  // ITERATION 1+
             memory.add(VOTE_TO_HALT, TraverserExecutor.execute(vertex, messenger, this.traversalMatrix, memory));
         }
+        this.traversal.get().getSideEffects().forEach((key, value) -> {
+            if (this.sideEffectKeys.contains(key) &&
+                    vertex.<Map<String, Object>>property(VertexTraversalSideEffects.SIDE_EFFECTS).value().containsKey(key)) {
+                memory.add(key, value);
+                vertex.<Map<String, Object>>property(VertexTraversalSideEffects.SIDE_EFFECTS).value().remove(key);
+            }
+        });
+
     }
 
     @Override
     public boolean terminate(final Memory memory) {
         final boolean voteToHalt = memory.<Boolean>get(VOTE_TO_HALT);
         if (voteToHalt) {
-            for (final ReducingBarrierStep<?, ?> reducingBarrierStep : TraversalHelper.getStepsOfAssignableClassRecursively(ReducingBarrierStep.class, this.traversal.get())) {
-                if (memory.exists(ReducingBarrierStep.REDUCING))
-                    memory.set(ReducingBarrierStep.REDUCING, reducingBarrierStep.generateFinalReduction(memory.get(ReducingBarrierStep.REDUCING)));
+            for (final GraphComputing graphComputing : TraversalHelper.getStepsOfAssignableClassRecursively(GraphComputing.class, this.traversal.get())) {
+                graphComputing.getMemoryComputeKey().ifPresent(key -> {
+                    memory.set(key.getKey(), graphComputing.generateFinalResult(memory.get(key.getKey())));
+                });
             }
             return true;
         } else {

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
index 69c84ad..f1f6b94 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
@@ -72,9 +72,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeOtherVertexSt
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeVertexStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.FoldStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupCountStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.GroupStepV3d0;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.IdStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.LabelStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.LambdaCollectingBarrierStep;
@@ -110,9 +107,9 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.UnfoldStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AddPropertyStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountSideEffectStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupSideEffectStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupSideEffectStepV3d0;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupCountStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupStepV3d0;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.GroupStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.IdentityStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.InjectStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.LambdaSideEffectStep;
@@ -147,6 +144,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.UUID;
 import java.util.function.BiFunction;
 import java.util.function.Consumer;
 import java.util.function.Function;
@@ -640,7 +638,8 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
     }
 
     public default <K, V> GraphTraversal<S, Map<K, V>> group() {
-        return this.asAdmin().addStep(new GroupStep<>(this.asAdmin()));
+        final String id = UUID.randomUUID().toString();
+        return this.asAdmin().addStep(new GroupStep<>(this.asAdmin(), id)).cap(id);
     }
 
     /**
@@ -648,11 +647,13 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
      */
     @Deprecated
     public default <K, V> GraphTraversal<S, Map<K, V>> groupV3d0() {
-        return this.asAdmin().addStep(new GroupStepV3d0<>(this.asAdmin()));
+        final String id = UUID.randomUUID().toString();
+        return this.asAdmin().addStep(new GroupStepV3d0<>(this.asAdmin(), id)).cap(id);
     }
 
     public default <K> GraphTraversal<S, Map<K, Long>> groupCount() {
-        return this.asAdmin().addStep(new GroupCountStep<>(this.asAdmin()));
+        final String id = UUID.randomUUID().toString() + "destroy";
+        return this.asAdmin().addStep(new GroupCountStep<>(this.asAdmin(), id)).cap(id);
     }
 
     public default GraphTraversal<S, Tree> tree() {
@@ -988,18 +989,18 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
     }
 
     public default GraphTraversal<S, E> group(final String sideEffectKey) {
-        return this.asAdmin().addStep(new GroupSideEffectStep<>(this.asAdmin(), sideEffectKey));
+        return this.asAdmin().addStep(new GroupStep<>(this.asAdmin(), sideEffectKey));
     }
 
     /**
      * @deprecated As of release 3.1.0, replaced by {@link #group(String)}.
      */
     public default GraphTraversal<S, E> groupV3d0(final String sideEffectKey) {
-        return this.asAdmin().addStep(new GroupSideEffectStepV3d0<>(this.asAdmin(), sideEffectKey));
+        return this.asAdmin().addStep(new GroupStepV3d0<>(this.asAdmin(), sideEffectKey));
     }
 
     public default GraphTraversal<S, E> groupCount(final String sideEffectKey) {
-        return this.asAdmin().addStep(new GroupCountSideEffectStep<>(this.asAdmin(), sideEffectKey));
+        return this.asAdmin().addStep(new GroupCountStep<>(this.asAdmin(), sideEffectKey));
     }
 
     public default GraphTraversal<S, E> tree(final String sideEffectKey) {

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GraphComputing.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GraphComputing.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GraphComputing.java
index 528f51c..941681f 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GraphComputing.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/GraphComputing.java
@@ -18,6 +18,10 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.step;
 
+import org.apache.tinkerpop.gremlin.process.computer.MemoryComputeKey;
+
+import java.util.Optional;
+
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
@@ -25,4 +29,11 @@ public interface GraphComputing {
 
     public void onGraphComputer();
 
+    public default Optional<MemoryComputeKey> getMemoryComputeKey() {
+        return Optional.empty();
+    }
+
+    public default Object generateFinalResult(final Object a) {
+        return a;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CountGlobalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CountGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CountGlobalStep.java
index 2c7cf0c..98a27fc 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CountGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/CountGlobalStep.java
@@ -18,6 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.step.map;
 
+import org.apache.tinkerpop.gremlin.process.computer.MemoryComputeKey;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.ReducingBarrierStep;
@@ -26,6 +27,7 @@ import org.apache.tinkerpop.gremlin.util.function.ConstantSupplier;
 
 import java.io.Serializable;
 import java.util.EnumSet;
+import java.util.Optional;
 import java.util.Set;
 import java.util.function.BinaryOperator;
 
@@ -39,7 +41,7 @@ public final class CountGlobalStep<S> extends ReducingBarrierStep<S, Long> {
     public CountGlobalStep(final Traversal.Admin traversal) {
         super(traversal);
         this.setSeedSupplier(new ConstantSupplier<>(0L));
-        this.setReducingBiOperator(new CountBiOperator());
+        this.setReducingBiOperator(CountBiOperator.INSTANCE);
     }
 
     @Override
@@ -53,10 +55,17 @@ public final class CountGlobalStep<S> extends ReducingBarrierStep<S, Long> {
         return REQUIREMENTS;
     }
 
+    @Override
+    public Optional<MemoryComputeKey> getMemoryComputeKey() {
+        return Optional.of(MemoryComputeKey.of(REDUCING, CountBiOperator.INSTANCE, false, false));
+    }
+
     ///////////
 
     public static class CountBiOperator implements BinaryOperator<Long>, Serializable {
 
+        private static final CountBiOperator INSTANCE = new CountBiOperator();
+
         @Override
         public Long apply(final Long mutatingSeed, final Long count) {
             return mutatingSeed + count;

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FoldStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FoldStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FoldStep.java
index 9194cf9..49b3961 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FoldStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/FoldStep.java
@@ -18,6 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.step.map;
 
+import org.apache.tinkerpop.gremlin.process.computer.MemoryComputeKey;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.ReducingBarrierStep;
@@ -28,6 +29,7 @@ import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.EnumSet;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
 import java.util.function.BiFunction;
 import java.util.function.BinaryOperator;
@@ -42,7 +44,7 @@ public final class FoldStep<S, E> extends ReducingBarrierStep<S, E> {
     private final boolean listFold;
 
     public FoldStep(final Traversal.Admin traversal) {
-        this(traversal, (Supplier) ArrayListSupplier.instance(), (BiFunction) new ListBiOperator<>());
+        this(traversal, (Supplier) ArrayListSupplier.instance(), ListBiOperator.INSTANCE);
     }
 
     public FoldStep(final Traversal.Admin traversal, final Supplier<E> seed, final BiFunction<E, S, E> foldFunction) {
@@ -53,6 +55,12 @@ public final class FoldStep<S, E> extends ReducingBarrierStep<S, E> {
     }
 
     @Override
+    public Optional<MemoryComputeKey> getMemoryComputeKey() {
+        return Optional.of(MemoryComputeKey.of(REDUCING, this.getBiOperator(), false, false));
+    }
+
+
+    @Override
     public E projectTraverser(final Traverser.Admin<S> traverser) {
         if (this.listFold) {
             final List<S> list = new ArrayList<>();
@@ -73,6 +81,9 @@ public final class FoldStep<S, E> extends ReducingBarrierStep<S, E> {
     /////////
 
     public static class ListBiOperator<S> implements BinaryOperator<List<S>>, Serializable {
+
+        private static final ListBiOperator INSTANCE = new ListBiOperator();
+
         @Override
         public List<S> apply(final List<S> mutatingSeed, final List<S> list) {
             mutatingSeed.addAll(list);

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStep.java
deleted file mode 100644
index 8180950..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStep.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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.step.map;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
-import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.MapHelper;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.ReducingBarrierStep;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
-import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import org.apache.tinkerpop.gremlin.util.function.HashMapSupplier;
-
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.BinaryOperator;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class GroupCountStep<S, E> extends ReducingBarrierStep<S, Map<E, Long>> implements TraversalParent, ByModulating {
-
-    private Traversal.Admin<S, E> keyTraversal = null;
-
-    public GroupCountStep(final Traversal.Admin traversal) {
-        super(traversal);
-        this.setSeedSupplier(HashMapSupplier.instance());
-        this.setReducingBiOperator(new GroupCountBiOperator());
-    }
-
-
-    @Override
-    public void modulateBy(final Traversal.Admin<?, ?> keyTraversal) {
-        this.keyTraversal = this.integrateChild(keyTraversal);
-    }
-
-    @Override
-    public List<Traversal.Admin<S, E>> getLocalChildren() {
-        return null == this.keyTraversal ? Collections.emptyList() : Collections.singletonList(this.keyTraversal);
-    }
-
-    public Map<E, Long> projectTraverser(final Traverser.Admin<S> traverser) {
-        return Collections.singletonMap(TraversalUtil.applyNullable(traverser, this.keyTraversal), traverser.bulk());
-    }
-
-    @Override
-    public Set<TraverserRequirement> getRequirements() {
-        return this.getSelfAndChildRequirements(TraverserRequirement.BULK);
-    }
-
-    @Override
-    public GroupCountStep<S, E> clone() {
-        final GroupCountStep<S, E> clone = (GroupCountStep<S, E>) super.clone();
-        if (null != this.keyTraversal)
-            clone.keyTraversal = clone.integrateChild(this.keyTraversal.clone());
-        return clone;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = super.hashCode();
-        for (final Traversal.Admin<S, E> traversal : this.getLocalChildren()) {
-            result ^= traversal.hashCode();
-        }
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return StringFactory.stepString(this, this.keyTraversal);
-    }
-
-    ///////////
-
-    public static final class GroupCountBiOperator<E> implements BinaryOperator<Map<E, Long>>, Serializable {
-
-        @Override
-        public Map<E, Long> apply(final Map<E, Long> mutatingSeed, final Map<E, Long> map) {
-            map.forEach((k, v) -> MapHelper.incr(mutatingSeed, k, v));
-            return mutatingSeed;
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java
deleted file mode 100644
index a6e9c66..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * 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.step.map;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
-import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.GroupStepHelper;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.ReducingBarrierStep;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
-import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import org.apache.tinkerpop.gremlin.util.function.HashMapSupplier;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.BinaryOperator;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class GroupStep<S, K, V> extends ReducingBarrierStep<S, Map<K, V>> implements TraversalParent, ByModulating {
-
-    private char state = 'k';
-
-    private Traversal.Admin<S, K> keyTraversal = null;
-    private Traversal.Admin<S, ?> valueTraversal = this.integrateChild(__.identity().asAdmin());   // used in OLAP
-    private Traversal.Admin<?, V> reduceTraversal = this.integrateChild(__.fold().asAdmin());      // used in OLAP
-    private Traversal.Admin<S, V> valueReduceTraversal = this.integrateChild(__.fold().asAdmin()); // used in OLTP
-
-    public GroupStep(final Traversal.Admin traversal) {
-        super(traversal);
-        this.setSeedSupplier(HashMapSupplier.instance());
-        this.setReducingBiOperator(new GroupBiOperator<>(this));
-    }
-
-    @Override
-    public void onGraphComputer() {
-        super.onGraphComputer();
-        this.setReducingBiOperator(new GroupBiOperator<>());
-    }
-
-    @Override
-    public Map<K, V> projectTraverser(final Traverser.Admin<S> traverser) {
-        final K key = TraversalUtil.applyNullable(traverser, this.keyTraversal);
-        final TraverserSet traverserSet = new TraverserSet();
-        if (this.onGraphComputer) {
-            this.valueTraversal.reset();
-            this.valueTraversal.addStart(traverser);
-            this.valueTraversal.getEndStep().forEachRemaining(t -> traverserSet.add(t.asAdmin()));
-        } else
-            traverserSet.add(traverser);
-
-        return Collections.singletonMap(key, (V) traverserSet);
-    }
-
-    @Override
-    public List<Traversal.Admin<?, ?>> getLocalChildren() {
-        final List<Traversal.Admin<?, ?>> children = new ArrayList<>(4);
-        if (null != this.keyTraversal)
-            children.add((Traversal.Admin) this.keyTraversal);
-        children.add(this.valueReduceTraversal);
-        children.add(this.valueTraversal);
-        children.add(this.reduceTraversal);
-        return children;
-    }
-
-    @Override
-    public void modulateBy(final Traversal.Admin<?, ?> kvTraversal) {
-        if ('k' == this.state) {
-            this.keyTraversal = this.integrateChild(kvTraversal);
-            this.state = 'v';
-        } else if ('v' == this.state) {
-            this.valueReduceTraversal = this.integrateChild(GroupStepHelper.convertValueTraversal(kvTraversal));
-            final List<Traversal.Admin<?, ?>> splitTraversal = GroupStepHelper.splitOnBarrierStep(this.valueReduceTraversal);
-            this.valueTraversal = this.integrateChild(splitTraversal.get(0));
-            this.reduceTraversal = this.integrateChild(splitTraversal.get(1));
-            this.state = 'x';
-        } else {
-            throw new IllegalStateException("The key and value traversals for group()-step have already been set: " + this);
-        }
-    }
-
-    @Override
-    public Set<TraverserRequirement> getRequirements() {
-        return this.getSelfAndChildRequirements(TraverserRequirement.OBJECT, TraverserRequirement.BULK);
-    }
-
-    @Override
-    public GroupStep<S, K, V> clone() {
-        final GroupStep<S, K, V> clone = (GroupStep<S, K, V>) super.clone();
-        if (null != this.keyTraversal)
-            clone.keyTraversal = clone.integrateChild(this.keyTraversal.clone());
-        clone.valueReduceTraversal = clone.integrateChild(this.valueReduceTraversal.clone());
-        clone.valueTraversal = clone.integrateChild(this.valueTraversal.clone());
-        clone.reduceTraversal = clone.integrateChild(this.reduceTraversal.clone());
-        return clone;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = this.valueReduceTraversal.hashCode();
-        if (this.keyTraversal != null) result ^= this.keyTraversal.hashCode();
-        return result;
-    }
-
-
-    @Override
-    public String toString() {
-        return StringFactory.stepString(this, this.keyTraversal, this.valueReduceTraversal);
-    }
-
-    @Override
-    public Map<K, V> generateFinalReduction(final Object traverserMap) {
-        final Map<K, V> reducedMap = new HashMap<>();
-        if (this.onGraphComputer) {
-            for (final K key : ((Map<K, TraverserSet>) traverserMap).keySet()) {
-                final Traversal.Admin<?, V> reduceClone = this.reduceTraversal.clone();
-                reduceClone.addStarts(((Map<K, TraverserSet>) traverserMap).get(key).iterator());
-                reducedMap.put(key, reduceClone.next());
-            }
-        } else {
-            for (final K key : ((Map<K, Traversal.Admin>) traverserMap).keySet()) {
-                reducedMap.put(key, (V) (((Map<K, Traversal.Admin>) traverserMap).get(key)).next());
-            }
-        }
-        return reducedMap;
-    }
-
-    ///////////
-
-    public static final class GroupBiOperator<K, V> implements BinaryOperator<Map<K, V>>, Serializable {
-
-        private transient GroupStep groupStep;
-        private final boolean onGraphComputer;
-
-        public GroupBiOperator(final GroupStep groupStep) {
-            this.groupStep = groupStep;
-            this.onGraphComputer = false;
-        }
-
-        public GroupBiOperator() {
-            this.onGraphComputer = true;
-        }
-
-        @Override
-        public Map<K, V> apply(final Map<K, V> mutatingSeed, final Map<K, V> map) {
-            for (final K key : map.keySet()) {
-                if (this.onGraphComputer) {
-                    TraverserSet<?> traverserSet = (TraverserSet) mutatingSeed.get(key);
-                    if (null == traverserSet) {
-                        traverserSet = new TraverserSet<>();
-                        mutatingSeed.put(key, (V) traverserSet);
-                    }
-                    traverserSet.addAll((TraverserSet) map.get(key));
-                } else {
-                    final TraverserSet<?> traverserSet = (TraverserSet<?>) map.get(key);
-                    Traversal.Admin valueReduceTraversal = (Traversal.Admin) mutatingSeed.get(key);
-                    if (null == valueReduceTraversal) {
-                        valueReduceTraversal = this.groupStep.valueReduceTraversal.clone();
-                        mutatingSeed.put(key, (V) valueReduceTraversal);
-                    }
-                    traverserSet.forEach(valueReduceTraversal::addStart);
-                }
-            }
-            return mutatingSeed;
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStepV3d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStepV3d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStepV3d0.java
deleted file mode 100644
index e4a8c9d..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStepV3d0.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * 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.step.map;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
-import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.ReducingBarrierStep;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
-import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import org.apache.tinkerpop.gremlin.util.function.HashMapSupplier;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.BinaryOperator;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-@Deprecated
-public final class GroupStepV3d0<S, K, V, R> extends ReducingBarrierStep<S, Map<K, R>> implements ByModulating, TraversalParent {
-
-    private char state = 'k';
-
-    private Traversal.Admin<S, K> keyTraversal = null;
-    private Traversal.Admin<S, V> valueTraversal = null;
-    private Traversal.Admin<Collection<V>, R> reduceTraversal = null;
-
-    public GroupStepV3d0(final Traversal.Admin traversal) {
-        super(traversal);
-        this.setSeedSupplier(HashMapSupplier.instance());
-        this.setReducingBiOperator(new GroupBiOperatorV3d0<>());
-    }
-
-    @Override
-    public Map<K, R> projectTraverser(final Traverser.Admin<S> traverser) {
-        final K key = TraversalUtil.applyNullable(traverser, this.keyTraversal);
-        final BulkSet<V> values = new BulkSet<>();
-        final V value = TraversalUtil.applyNullable(traverser, this.valueTraversal);
-        TraversalHelper.addToCollectionUnrollIterator(values, value, traverser.bulk());
-        return Collections.singletonMap(key, (R) values);
-    }
-
-    @Override
-    public <A, B> List<Traversal.Admin<A, B>> getLocalChildren() {
-        final List<Traversal.Admin<A, B>> children = new ArrayList<>(3);
-        if (null != this.keyTraversal)
-            children.add((Traversal.Admin) this.keyTraversal);
-        if (null != this.valueTraversal)
-            children.add((Traversal.Admin) this.valueTraversal);
-        if (null != this.reduceTraversal)
-            children.add((Traversal.Admin) this.reduceTraversal);
-        return children;
-    }
-
-    @Override
-    public void modulateBy(final Traversal.Admin<?, ?> kvrTraversal) {
-        if ('k' == this.state) {
-            this.keyTraversal = this.integrateChild(kvrTraversal);
-            this.state = 'v';
-        } else if ('v' == this.state) {
-            this.valueTraversal = this.integrateChild(kvrTraversal);
-            this.state = 'r';
-        } else if ('r' == this.state) {
-            this.reduceTraversal = this.integrateChild(kvrTraversal);
-            this.state = 'x';
-        } else {
-            throw new IllegalStateException("The key, value, and reduce functions for group()-step have already been set");
-        }
-    }
-
-    @Override
-    public Set<TraverserRequirement> getRequirements() {
-        return this.getSelfAndChildRequirements(TraverserRequirement.SIDE_EFFECTS, TraverserRequirement.BULK);
-    }
-
-    @Override
-    public GroupStepV3d0<S, K, V, R> clone() {
-        final GroupStepV3d0<S, K, V, R> clone = (GroupStepV3d0<S, K, V, R>) super.clone();
-        if (null != this.keyTraversal)
-            clone.keyTraversal = clone.integrateChild(this.keyTraversal.clone());
-        if (null != this.valueTraversal)
-            clone.valueTraversal = clone.integrateChild(this.valueTraversal.clone());
-        if (null != this.reduceTraversal)
-            clone.reduceTraversal = clone.integrateChild(this.reduceTraversal.clone());
-        return clone;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = super.hashCode();
-        for (final Traversal.Admin traversal : this.getLocalChildren()) {
-            result ^= traversal.hashCode();
-        }
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return StringFactory.stepString(this, this.keyTraversal, this.valueTraversal, this.reduceTraversal);
-    }
-
-    @Override
-    public Map<K, R> generateFinalReduction(final Object valueMap) {
-        final Map<K, R> reducedMap = new HashMap<>();
-        for (final K key : ((Map<K, Collection<V>>) valueMap).keySet()) {
-            final R r = TraversalUtil.applyNullable(((Map<K, Collection<V>>) valueMap).get(key), this.reduceTraversal);
-            reducedMap.put(key, r);
-        }
-        return reducedMap;
-    }
-
-    ////////////
-
-    public static class GroupBiOperatorV3d0<K, V> implements BinaryOperator<Map<K, V>>, Serializable {
-
-        private GroupBiOperatorV3d0() {
-
-        }
-
-        @Override
-        public Map<K, V> apply(final Map<K, V> mutatingSeed, final Map<K, V> map) {
-            for (final K key : map.keySet()) {
-                final BulkSet<V> values = (BulkSet<V>) map.get(key);
-                BulkSet<V> seedValues = (BulkSet<V>) mutatingSeed.get(key);
-                if (null == seedValues) {
-                    seedValues = new BulkSet<>();
-                    mutatingSeed.put(key, (V) seedValues);
-                }
-                seedValues.addAll(values);
-            }
-            return mutatingSeed;
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MaxGlobalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MaxGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MaxGlobalStep.java
index c9466db..c409ae4 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MaxGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MaxGlobalStep.java
@@ -18,6 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.step.map;
 
+import org.apache.tinkerpop.gremlin.process.computer.MemoryComputeKey;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.ReducingBarrierStep;
@@ -26,6 +27,7 @@ import org.apache.tinkerpop.gremlin.util.function.ConstantSupplier;
 
 import java.io.Serializable;
 import java.util.Collections;
+import java.util.Optional;
 import java.util.Set;
 import java.util.function.BinaryOperator;
 
@@ -46,11 +48,16 @@ public final class MaxGlobalStep<S extends Number> extends ReducingBarrierStep<S
     }
 
     @Override
-    public S projectTraverser(final Traverser.Admin<S> traverser) {
+    public S projectTraverser(Traverser.Admin<S> traverser) {
         return traverser.get();
     }
 
     @Override
+    public Optional<MemoryComputeKey> getMemoryComputeKey() {
+        return Optional.of(MemoryComputeKey.of(REDUCING, MaxGlobalBiOperator.INSTANCE, false, false));
+    }
+
+    @Override
     public Set<TraverserRequirement> getRequirements() {
         return Collections.singleton(TraverserRequirement.OBJECT);
     }
@@ -58,6 +65,9 @@ public final class MaxGlobalStep<S extends Number> extends ReducingBarrierStep<S
     /////
 
     public static class MaxGlobalBiOperator<S extends Number> implements BinaryOperator<S>, Serializable {
+
+        private static final MaxGlobalBiOperator INSTANCE = new MaxGlobalBiOperator();
+
         @Override
         public S apply(final S mutatingSeed, final S number) {
             return !NAN.equals(mutatingSeed) ? (S) max(mutatingSeed, number) : number;

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MeanGlobalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MeanGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MeanGlobalStep.java
index c5912e5..53306b2 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MeanGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MeanGlobalStep.java
@@ -18,6 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.step.map;
 
+import org.apache.tinkerpop.gremlin.process.computer.MemoryComputeKey;
 import org.apache.tinkerpop.gremlin.process.traversal.NumberHelper;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
@@ -28,6 +29,7 @@ import org.apache.tinkerpop.gremlin.util.function.MeanNumberSupplier;
 
 import java.io.Serializable;
 import java.util.EnumSet;
+import java.util.Optional;
 import java.util.Set;
 import java.util.function.BinaryOperator;
 import java.util.function.Supplier;
@@ -46,7 +48,7 @@ public final class MeanGlobalStep<S extends Number, E extends Number> extends Re
     public MeanGlobalStep(final Traversal.Admin traversal) {
         super(traversal);
         this.setSeedSupplier((Supplier) MeanNumberSupplier.instance());
-        this.setReducingBiOperator(new MeanGlobalBiOperator<>());
+        this.setReducingBiOperator(MeanGlobalBiOperator.INSTANCE);
     }
 
     @Override
@@ -60,14 +62,21 @@ public final class MeanGlobalStep<S extends Number, E extends Number> extends Re
     }
 
     @Override
-    public E generateFinalReduction(final Object reduction) {
-        return (E) ((MeanNumber) reduction).getFinal();
+    public Optional<MemoryComputeKey> getMemoryComputeKey() {
+        return Optional.of(MemoryComputeKey.of(REDUCING, MeanGlobalBiOperator.INSTANCE, false, false));
+    }
+
+    @Override
+    public Object generateFinalResult(final Object a) {
+        return ((MeanNumber) a).getFinal();
     }
 
     /////
 
     public static final class MeanGlobalBiOperator<S extends Number> implements BinaryOperator<S>, Serializable {
 
+        private static MeanGlobalBiOperator INSTANCE = new MeanGlobalBiOperator();
+
         @Override
         public S apply(final S mutatingSeed, final S number) {
             if (mutatingSeed instanceof MeanNumber) {

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MinGlobalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MinGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MinGlobalStep.java
index bdcad4c..a90419e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MinGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MinGlobalStep.java
@@ -18,6 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.step.map;
 
+import org.apache.tinkerpop.gremlin.process.computer.MemoryComputeKey;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.ReducingBarrierStep;
@@ -26,6 +27,7 @@ import org.apache.tinkerpop.gremlin.util.function.ConstantSupplier;
 
 import java.io.Serializable;
 import java.util.Collections;
+import java.util.Optional;
 import java.util.Set;
 import java.util.function.BinaryOperator;
 
@@ -41,7 +43,7 @@ public final class MinGlobalStep<S extends Number> extends ReducingBarrierStep<S
     public MinGlobalStep(final Traversal.Admin traversal) {
         super(traversal);
         this.setSeedSupplier(new ConstantSupplier<>((S) NAN));
-        this.setReducingBiOperator(new MinGlobalBiOperator<>());
+        this.setReducingBiOperator(MinGlobalBiOperator.INSTANCE);
     }
 
     @Override
@@ -54,9 +56,17 @@ public final class MinGlobalStep<S extends Number> extends ReducingBarrierStep<S
         return Collections.singleton(TraverserRequirement.OBJECT);
     }
 
+    @Override
+    public Optional<MemoryComputeKey> getMemoryComputeKey() {
+        return Optional.of(MemoryComputeKey.of(REDUCING, MinGlobalBiOperator.INSTANCE, false, false));
+    }
+
     /////
 
     public static class MinGlobalBiOperator<S extends Number> implements BinaryOperator<S>, Serializable {
+
+        private static final MinGlobalBiOperator INSTANCE = new MinGlobalBiOperator();
+
         @Override
         public S apply(final S mutatingSeed, final S number) {
             return !NAN.equals(mutatingSeed) ? (S) min(mutatingSeed, number) : number;

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SumGlobalStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SumGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SumGlobalStep.java
index 2311344..42bbad0 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SumGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SumGlobalStep.java
@@ -18,6 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.step.map;
 
+import org.apache.tinkerpop.gremlin.process.computer.MemoryComputeKey;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.ReducingBarrierStep;
@@ -26,6 +27,7 @@ import org.apache.tinkerpop.gremlin.util.function.ConstantSupplier;
 
 import java.io.Serializable;
 import java.util.EnumSet;
+import java.util.Optional;
 import java.util.Set;
 import java.util.function.BinaryOperator;
 
@@ -45,7 +47,7 @@ public final class SumGlobalStep<S extends Number> extends ReducingBarrierStep<S
     public SumGlobalStep(final Traversal.Admin traversal) {
         super(traversal);
         this.setSeedSupplier(new ConstantSupplier<>((S) Integer.valueOf(0)));
-        this.setReducingBiOperator(new SumGlobalBiOperator<S>());
+        this.setReducingBiOperator(SumGlobalBiOperator.INSTANCE);
     }
 
     @Override
@@ -59,10 +61,17 @@ public final class SumGlobalStep<S extends Number> extends ReducingBarrierStep<S
         return REQUIREMENTS;
     }
 
+    @Override
+    public Optional<MemoryComputeKey> getMemoryComputeKey() {
+        return Optional.of(MemoryComputeKey.of(REDUCING, SumGlobalBiOperator.INSTANCE, false, false));
+    }
+
     /////
 
     public static class SumGlobalBiOperator<S extends Number> implements BinaryOperator<S>, Serializable {
 
+        private static final SumGlobalBiOperator INSTANCE = new SumGlobalBiOperator();
+
         @Override
         public S apply(final S mutatingSeed, final S number) {
             return (S) add(mutatingSeed, number);

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java
index 3aeecbf..1d4902d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java
@@ -18,6 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.process.traversal.step.map;
 
+import org.apache.tinkerpop.gremlin.process.computer.MemoryComputeKey;
 import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
@@ -34,6 +35,7 @@ import org.apache.tinkerpop.gremlin.util.function.TreeSupplier;
 
 import java.io.Serializable;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
 import java.util.function.BinaryOperator;
 import java.util.function.Supplier;
@@ -48,7 +50,12 @@ public final class TreeStep<S> extends ReducingBarrierStep<S, Tree> implements T
     public TreeStep(final Traversal.Admin traversal) {
         super(traversal);
         this.setSeedSupplier((Supplier) TreeSupplier.instance());
-        this.setReducingBiOperator(new TreeBiOperator());
+        this.setReducingBiOperator(TreeBiOperator.INSTANCE);
+    }
+
+    @Override
+    public Optional<MemoryComputeKey> getMemoryComputeKey() {
+        return Optional.of(MemoryComputeKey.of(REDUCING, TreeBiOperator.INSTANCE, false, false));
     }
 
 
@@ -111,6 +118,8 @@ public final class TreeStep<S> extends ReducingBarrierStep<S, Tree> implements T
 
     public static final class TreeBiOperator implements BinaryOperator<Tree>, Serializable {
 
+        private static final TreeBiOperator INSTANCE = new TreeBiOperator();
+
         @Override
         public Tree apply(final Tree mutatingSeed, final Tree tree) {
             mutatingSeed.addTree(tree);

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountSideEffectStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountSideEffectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountSideEffectStep.java
deleted file mode 100644
index 0da6d51..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountSideEffectStep.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * 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.step.sideEffect;
-
-import org.apache.commons.configuration.Configuration;
-import org.apache.tinkerpop.gremlin.process.computer.KeyValue;
-import org.apache.tinkerpop.gremlin.process.computer.MapReduce;
-import org.apache.tinkerpop.gremlin.process.computer.traversal.TraversalVertexProgram;
-import org.apache.tinkerpop.gremlin.process.computer.traversal.VertexTraversalSideEffects;
-import org.apache.tinkerpop.gremlin.process.computer.util.StaticMapReduce;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
-import org.apache.tinkerpop.gremlin.process.traversal.step.MapReducer;
-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.util.MapHelper;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import org.apache.tinkerpop.gremlin.util.function.HashMapSupplier;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Supplier;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class GroupCountSideEffectStep<S, E> extends SideEffectStep<S> implements SideEffectCapable, TraversalParent, ByModulating, MapReducer<E, Long, E, Long, Map<E, Long>> {
-
-    private Traversal.Admin<S, E> groupTraversal = null;
-    private String sideEffectKey;
-
-    public GroupCountSideEffectStep(final Traversal.Admin traversal, final String sideEffectKey) {
-        super(traversal);
-        this.sideEffectKey = sideEffectKey;
-        this.traversal.asAdmin().getSideEffects().registerSupplierIfAbsent(this.sideEffectKey, HashMapSupplier.instance());
-    }
-
-    @Override
-    protected void sideEffect(final Traverser.Admin<S> traverser) {
-        final Map<Object, Long> groupCountMap = traverser.sideEffects(this.sideEffectKey);
-        MapHelper.incr(groupCountMap, TraversalUtil.applyNullable(traverser.asAdmin(), this.groupTraversal), traverser.bulk());
-    }
-
-    @Override
-    public String getSideEffectKey() {
-        return this.sideEffectKey;
-    }
-
-    @Override
-    public MapReduce<E, Long, E, Long, Map<E, Long>> getMapReduce() {
-        return new GroupCountSideEffectMapReduce<>(this);
-    }
-
-    @Override
-    public String toString() {
-        return StringFactory.stepString(this, this.sideEffectKey, this.groupTraversal);
-    }
-
-    @Override
-    public void addLocalChild(final Traversal.Admin<?, ?> groupTraversal) {
-        this.groupTraversal = this.integrateChild(groupTraversal);
-    }
-
-    @Override
-    public List<Traversal.Admin<S, E>> getLocalChildren() {
-        return null == this.groupTraversal ? Collections.emptyList() : Collections.singletonList(this.groupTraversal);
-    }
-
-    @Override
-    public Set<TraverserRequirement> getRequirements() {
-        return this.getSelfAndChildRequirements(TraverserRequirement.BULK, TraverserRequirement.SIDE_EFFECTS);
-    }
-
-    @Override
-    public GroupCountSideEffectStep<S, E> clone() {
-        final GroupCountSideEffectStep<S, E> clone = (GroupCountSideEffectStep<S, E>) super.clone();
-        if (null != this.groupTraversal)
-            clone.groupTraversal = clone.integrateChild(this.groupTraversal.clone());
-        return clone;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = super.hashCode() ^ this.sideEffectKey.hashCode();
-        if (this.groupTraversal != null) result ^= this.groupTraversal.hashCode();
-        return result;
-    }
-
-    @Override
-    public void modulateBy(final Traversal.Admin<?,?> keyTraversal) throws UnsupportedOperationException {
-        this.groupTraversal = this.integrateChild(keyTraversal);
-    }
-
-    ///////
-
-    public static final class GroupCountSideEffectMapReduce<E> extends StaticMapReduce<E, Long, E, Long, Map<E, Long>> {
-
-        public static final String GROUP_COUNT_SIDE_EFFECT_STEP_SIDE_EFFECT_KEY = "gremlin.groupCountSideEffectStep.sideEffectKey";
-
-        private String sideEffectKey;
-        private Supplier<Map<E, Long>> mapSupplier;
-
-        private GroupCountSideEffectMapReduce() {
-
-        }
-
-        public GroupCountSideEffectMapReduce(final GroupCountSideEffectStep step) {
-            this.sideEffectKey = step.getSideEffectKey();
-            this.mapSupplier = step.getTraversal().asAdmin().getSideEffects().<Map<E, Long>>getRegisteredSupplier(this.sideEffectKey).orElse(HashMap::new);
-        }
-
-        @Override
-        public void storeState(final Configuration configuration) {
-            super.storeState(configuration);
-            configuration.setProperty(GROUP_COUNT_SIDE_EFFECT_STEP_SIDE_EFFECT_KEY, this.sideEffectKey);
-        }
-
-        @Override
-        public void loadState(final Graph graph, final Configuration configuration) {
-            this.sideEffectKey = configuration.getString(GROUP_COUNT_SIDE_EFFECT_STEP_SIDE_EFFECT_KEY);
-            this.mapSupplier = TraversalVertexProgram.getTraversal(graph, configuration).getSideEffects().<Map<E, Long>>getRegisteredSupplier(this.sideEffectKey).orElse(HashMap::new);
-        }
-
-        @Override
-        public boolean doStage(final Stage stage) {
-            return true;
-        }
-
-        @Override
-        public void map(final Vertex vertex, final MapEmitter<E, Long> emitter) {
-            VertexTraversalSideEffects.of(vertex).<Map<E, Number>>get(this.sideEffectKey).ifPresent(map -> map.forEach((k, v) -> emitter.emit(k, v.longValue())));
-        }
-
-        @Override
-        public void reduce(final E key, final Iterator<Long> values, final ReduceEmitter<E, Long> emitter) {
-            long counter = 0;
-            while (values.hasNext()) {
-                counter = counter + values.next();
-            }
-            emitter.emit(key, counter);
-        }
-
-        @Override
-        public void combine(final E key, final Iterator<Long> values, final ReduceEmitter<E, Long> emitter) {
-            reduce(key, values, emitter);
-        }
-
-        @Override
-        public Map<E, Long> generateFinalResult(final Iterator<KeyValue<E, Long>> keyValues) {
-            final Map<E, Long> map = this.mapSupplier.get();
-            keyValues.forEachRemaining(keyValue -> map.put(keyValue.getKey(), keyValue.getValue()));
-            return map;
-        }
-
-        @Override
-        public String getMemoryKey() {
-            return this.sideEffectKey;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountStep.java
new file mode 100644
index 0000000..1a655ea
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupCountStep.java
@@ -0,0 +1,134 @@
+/*
+ * 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.step.sideEffect;
+
+import org.apache.tinkerpop.gremlin.process.computer.MemoryComputeKey;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
+import org.apache.tinkerpop.gremlin.process.traversal.step.GraphComputing;
+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.util.MapHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
+import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+import org.apache.tinkerpop.gremlin.util.function.HashMapSupplier;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.BinaryOperator;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class GroupCountStep<S, E> extends SideEffectStep<S> implements SideEffectCapable, GraphComputing, TraversalParent, ByModulating {
+
+    private Traversal.Admin<S, E> keyTraversal = null;
+    private String sideEffectKey;
+
+    public GroupCountStep(final Traversal.Admin traversal, final String sideEffectKey) {
+        super(traversal);
+        this.sideEffectKey = sideEffectKey;
+        this.traversal.asAdmin().getSideEffects().registerSupplierIfAbsent(this.sideEffectKey, HashMapSupplier.instance());
+    }
+
+    @Override
+    protected void sideEffect(final Traverser.Admin<S> traverser) {
+        final Map<Object, Long> groupCountMap = traverser.sideEffects(this.sideEffectKey);
+        MapHelper.incr(groupCountMap, TraversalUtil.applyNullable(traverser.asAdmin(), this.keyTraversal), traverser.bulk());
+    }
+
+    @Override
+    public String getSideEffectKey() {
+        return this.sideEffectKey;
+    }
+
+    @Override
+    public String toString() {
+        return StringFactory.stepString(this, this.sideEffectKey, this.keyTraversal);
+    }
+
+    @Override
+    public void addLocalChild(final Traversal.Admin<?, ?> groupTraversal) {
+        this.keyTraversal = this.integrateChild(groupTraversal);
+    }
+
+    @Override
+    public List<Traversal.Admin<S, E>> getLocalChildren() {
+        return null == this.keyTraversal ? Collections.emptyList() : Collections.singletonList(this.keyTraversal);
+    }
+
+    @Override
+    public Set<TraverserRequirement> getRequirements() {
+        return this.getSelfAndChildRequirements(TraverserRequirement.BULK, TraverserRequirement.SIDE_EFFECTS);
+    }
+
+    @Override
+    public GroupCountStep<S, E> clone() {
+        final GroupCountStep<S, E> clone = (GroupCountStep<S, E>) super.clone();
+        if (null != this.keyTraversal)
+            clone.keyTraversal = clone.integrateChild(this.keyTraversal.clone());
+        return clone;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = super.hashCode() ^ this.sideEffectKey.hashCode();
+        if (this.keyTraversal != null) result ^= this.keyTraversal.hashCode();
+        return result;
+    }
+
+    @Override
+    public void modulateBy(final Traversal.Admin<?, ?> keyTraversal) throws UnsupportedOperationException {
+        this.keyTraversal = this.integrateChild(keyTraversal);
+    }
+
+    @Override
+    public void onGraphComputer() {
+
+    }
+
+    @Override
+    public Object generateFinalResult(final Object map) {
+        return map;
+    }
+
+    @Override
+    public Optional<MemoryComputeKey> getMemoryComputeKey() {
+        return Optional.of(MemoryComputeKey.of(this.getSideEffectKey(), GroupCountBiOperator.INSTANCE, false, false));
+    }
+
+    ///////
+
+    public static final class GroupCountBiOperator<E> implements BinaryOperator<Map<E, Long>>, Serializable {
+
+        private static GroupCountBiOperator INSTANCE = new GroupCountBiOperator();
+
+        @Override
+        public Map<E, Long> apply(final Map<E, Long> mutatingSeed, final Map<E, Long> map) {
+            map.forEach((k, v) -> MapHelper.incr(mutatingSeed, k, v));
+            return mutatingSeed;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/aa79390f/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStep.java
deleted file mode 100644
index cdc8ac9..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupSideEffectStep.java
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * 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.step.sideEffect;
-
-import org.apache.commons.configuration.Configuration;
-import org.apache.tinkerpop.gremlin.process.computer.KeyValue;
-import org.apache.tinkerpop.gremlin.process.computer.MapReduce;
-import org.apache.tinkerpop.gremlin.process.computer.traversal.TraversalVertexProgram;
-import org.apache.tinkerpop.gremlin.process.computer.traversal.VertexTraversalSideEffects;
-import org.apache.tinkerpop.gremlin.process.traversal.Step;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
-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.ByModulating;
-import org.apache.tinkerpop.gremlin.process.traversal.step.GraphComputing;
-import org.apache.tinkerpop.gremlin.process.traversal.step.MapReducer;
-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.util.BulkSet;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.GroupStepHelper;
-import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMatrix;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import org.apache.tinkerpop.gremlin.util.function.HashMapSupplier;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Supplier;
-
-/**
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-public final class GroupSideEffectStep<S, K, V> extends SideEffectStep<S> implements SideEffectCapable, TraversalParent, ByModulating, GraphComputing, MapReducer<K, Collection<?>, K, V, Map<K, V>> {
-
-    private char state = 'k';
-    private Traversal.Admin<S, K> keyTraversal = null;
-    private Traversal.Admin<S, ?> valueTraversal = this.integrateChild(__.identity().asAdmin());   // used in OLAP
-    private Traversal.Admin<?, V> reduceTraversal = this.integrateChild(__.fold().asAdmin());      // used in OLAP
-    private Traversal.Admin<S, V> valueReduceTraversal = this.integrateChild(__.fold().asAdmin()); // used in OLTP
-    ///
-    private String sideEffectKey;
-    private boolean onGraphComputer = false;
-    private GroupStepHelper.GroupMap<S, K, V> groupMap;
-    private final Map<K, Integer> counters = new HashMap<>();
-
-    public GroupSideEffectStep(final Traversal.Admin traversal, final String sideEffectKey) {
-        super(traversal);
-        this.sideEffectKey = sideEffectKey;
-        this.traversal.asAdmin().getSideEffects().registerSupplierIfAbsent(this.sideEffectKey, HashMapSupplier.instance());
-    }
-
-    @Override
-    public void modulateBy(final Traversal.Admin<?, ?> kvTraversal) {
-        if ('k' == this.state) {
-            this.keyTraversal = this.integrateChild(kvTraversal);
-            this.state = 'v';
-        } else if ('v' == this.state) {
-            this.valueReduceTraversal = this.integrateChild(GroupStepHelper.convertValueTraversal(kvTraversal));
-            final List<Traversal.Admin<?, ?>> splitTraversal = GroupStepHelper.splitOnBarrierStep(this.valueReduceTraversal);
-            this.valueTraversal = this.integrateChild(splitTraversal.get(0));
-            this.reduceTraversal = this.integrateChild(splitTraversal.get(1));
-            this.state = 'x';
-        } else {
-            throw new IllegalStateException("The key and value traversals for group()-step have already been set: " + this);
-        }
-    }
-
-    @Override
-    protected void sideEffect(final Traverser.Admin<S> traverser) {
-        if (this.onGraphComputer) {      // OLAP
-            final Map<K, Collection<?>> map = traverser.sideEffects(this.sideEffectKey);
-            final K key = TraversalUtil.applyNullable(traverser, this.keyTraversal);
-            Collection<?> values = map.get(key);
-            if (null == values) {
-                values = new BulkSet<>();
-                map.put(key, values);
-            }
-            this.valueTraversal.addStart(traverser.clone()); // the full traverser is provided (not a bulk 1 traverser) and clone is needed cause sideEffect steps don't split the traverser
-            this.valueTraversal.fill((Collection) values);
-        } else {                        // OLTP
-            if (null == this.groupMap) {
-                final Object object = traverser.sideEffects(this.sideEffectKey);
-                if (!(object instanceof GroupStepHelper.GroupMap))
-                    traverser.sideEffects(this.sideEffectKey, this.groupMap = new GroupStepHelper.GroupMap<>((Map<K, V>) object));
-            }
-            final K key = TraversalUtil.applyNullable(traverser, this.keyTraversal);
-            Traversal.Admin<S, V> traversal = this.groupMap.get(key);
-            if (null == traversal) {
-                traversal = this.valueReduceTraversal.clone();
-                this.groupMap.put(key, traversal);
-                this.counters.put(key, 0);
-            }
-            traversal.addStart(traverser.clone()); // this is because sideEffect steps don't split the traverser
-            final int count = this.counters.compute(key, (k, i) -> ++i);
-            if (count > 10000) {
-                this.counters.put(key, 0);
-                TraversalHelper.getFirstStepOfAssignableClass(Barrier.class, traversal).ifPresent(Barrier::processAllStarts);
-            }
-        }
-    }
-
-    @Override
-    public String getSideEffectKey() {
-        return this.sideEffectKey;
-    }
-
-    @Override
-    public void onGraphComputer() {
-        this.onGraphComputer = true;
-    }
-
-    @Override
-    public MapReduce<K, Collection<?>, K, V, Map<K, V>> getMapReduce() {
-        return new GroupSideEffectMapReduce<>(this);
-    }
-
-    @Override
-    public String toString() {
-        return StringFactory.stepString(this, this.sideEffectKey, this.keyTraversal, this.valueReduceTraversal);
-    }
-
-    @Override
-    public List<Traversal.Admin<?, ?>> getLocalChildren() {
-        final List<Traversal.Admin<?, ?>> children = new ArrayList<>(4);
-        if (null != this.keyTraversal)
-            children.add((Traversal.Admin) this.keyTraversal);
-        children.add(this.valueReduceTraversal);
-        children.add(this.valueTraversal);
-        children.add(this.reduceTraversal);
-        return children;
-    }
-
-    @Override
-    public Set<TraverserRequirement> getRequirements() {
-        return this.getSelfAndChildRequirements(TraverserRequirement.OBJECT, TraverserRequirement.BULK, TraverserRequirement.SIDE_EFFECTS);
-    }
-
-    @Override
-    public GroupSideEffectStep<S, K, V> clone() {
-        final GroupSideEffectStep<S, K, V> clone = (GroupSideEffectStep<S, K, V>) super.clone();
-        if (null != this.keyTraversal)
-            clone.keyTraversal = clone.integrateChild(this.keyTraversal.clone());
-        clone.valueReduceTraversal = clone.integrateChild(this.valueReduceTraversal.clone());
-        clone.valueTraversal = clone.integrateChild(this.valueTraversal.clone());
-        clone.reduceTraversal = clone.integrateChild(this.reduceTraversal.clone());
-        return clone;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = super.hashCode() ^ this.sideEffectKey.hashCode();
-        if (this.keyTraversal != null) result ^= this.keyTraversal.hashCode();
-        result ^= this.valueReduceTraversal.hashCode();
-        return result;
-    }
-
-    ///////////
-
-    public static final class GroupSideEffectMapReduce<S, K, V> implements MapReduce<K, Collection<?>, K, V, Map<K, V>> {
-
-        public static final String GROUP_SIDE_EFFECT_STEP_SIDE_EFFECT_KEY = "gremlin.groupSideEffectStep.sideEffectKey";
-        public static final String GROUP_SIDE_EFFECT_STEP_STEP_ID = "gremlin.groupSideEffectStep.stepId";
-
-        private String sideEffectKey;
-        private String groupStepId;
-        private Traversal.Admin<?, V> reduceTraversal;
-        private Supplier<Map<K, V>> mapSupplier;
-
-        private GroupSideEffectMapReduce() {
-
-        }
-
-        public GroupSideEffectMapReduce(final GroupSideEffectStep<S, K, V> step) {
-            this.groupStepId = step.getId();
-            this.sideEffectKey = step.getSideEffectKey();
-            this.reduceTraversal = step.reduceTraversal.clone();
-            this.mapSupplier = step.getTraversal().asAdmin().getSideEffects().<Map<K, V>>getRegisteredSupplier(this.sideEffectKey).orElse(HashMapSupplier.instance());
-        }
-
-        @Override
-        public void storeState(final Configuration configuration) {
-            MapReduce.super.storeState(configuration);
-            configuration.setProperty(GROUP_SIDE_EFFECT_STEP_SIDE_EFFECT_KEY, this.sideEffectKey);
-            configuration.setProperty(GROUP_SIDE_EFFECT_STEP_STEP_ID, this.groupStepId);
-        }
-
-        @Override
-        public void loadState(final Graph graph, final Configuration configuration) {
-            this.sideEffectKey = configuration.getString(GROUP_SIDE_EFFECT_STEP_SIDE_EFFECT_KEY);
-            this.groupStepId = configuration.getString(GROUP_SIDE_EFFECT_STEP_STEP_ID);
-            final Traversal.Admin<?, ?> traversal = TraversalVertexProgram.getTraversal(graph, configuration);
-            final GroupSideEffectStep<S, K, V> groupSideEffectStep = new TraversalMatrix<>(traversal).getStepById(this.groupStepId);
-            this.reduceTraversal = groupSideEffectStep.reduceTraversal.clone();
-            this.mapSupplier = traversal.getSideEffects().<Map<K, V>>getRegisteredSupplier(this.sideEffectKey).orElse(HashMapSupplier.instance());
-        }
-
-        @Override
-        public boolean doStage(final Stage stage) {
-            return !stage.equals(Stage.COMBINE);
-        }
-
-        @Override
-        public void map(final Vertex vertex, final MapEmitter<K, Collection<?>> emitter) {
-            VertexTraversalSideEffects.of(vertex).<Map<K, Collection<?>>>get(this.sideEffectKey).ifPresent(map -> map.forEach(emitter::emit));
-        }
-
-        @Override
-        public void reduce(final K key, final Iterator<Collection<?>> values, final ReduceEmitter<K, V> emitter) {
-            Traversal.Admin<?, V> reduceTraversalClone = this.reduceTraversal.clone();
-            while (values.hasNext()) {
-                final BulkSet<?> value = (BulkSet<?>) values.next();
-                value.forEach((v, bulk) -> reduceTraversalClone.addStart(reduceTraversalClone.getTraverserGenerator().generate(v, (Step) reduceTraversalClone.getStartStep(), bulk)));
-                TraversalHelper.getFirstStepOfAssignableClass(Barrier.class, reduceTraversalClone).ifPresent(Barrier::processAllStarts);
-            }
-            emitter.emit(key, reduceTraversalClone.next());
-        }
-
-        @Override
-        public Map<K, V> generateFinalResult(final Iterator<KeyValue<K, V>> keyValues) {
-            final Map<K, V> map = this.mapSupplier.get();
-            keyValues.forEachRemaining(keyValue -> map.put(keyValue.getKey(), keyValue.getValue()));
-            return map;
-        }
-
-        @Override
-        public String getMemoryKey() {
-            return this.sideEffectKey;
-        }
-
-        @Override
-        public GroupSideEffectMapReduce<S, K, V> clone() {
-            try {
-                final GroupSideEffectMapReduce<S, K, V> clone = (GroupSideEffectMapReduce<S, K, V>) super.clone();
-                clone.reduceTraversal = this.reduceTraversal.clone();
-                return clone;
-            } catch (final CloneNotSupportedException e) {
-                throw new IllegalStateException(e.getMessage(), e);
-            }
-        }
-
-        @Override
-        public String toString() {
-            return StringFactory.mapReduceString(this, this.getMemoryKey());
-        }
-    }
-}