anchor.diff:  Distributed Gremlin Gotchas
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
   
  -Gremlin evaluated on a single machine is not identical to Gremlin evaluated in a multi-machine compute cluster.
  -
  -IMPORTANT: There are two primary theoretical differences between Gremlin OLTP and Gremlin OLAP. First, Gremlin OLTP (via `Traversal`) leverages a link:http://en.wikipedia.org/wiki/Depth-first_search[depth-first] execution engine. Depth-first execution requires a limited memory footprint due to link:http://en.wikipedia.org/wiki/Lazy_evaluation[lazy evaluation]. On the other hand, Gremlin OLAP (via `TraversalVertexProgram`) leverages a link:http://en.wikipedia.org/wiki/Breadth-first_search[breadth-first] execution engine which has a large memory footprint, but a better time complexity due to vertex-local traversers being able to be merged. The second difference is that Gremlin OLTP is executed in a serial fashion, while Gremlin OLAP is executed in a distributed fashion. These two fundamental differences leads to the different behaviors enumerated below.
  +Gremlin OLTP is not identical to Gremlin OLAP.
  +
  +IMPORTANT: There are two primary theoretical differences between Gremlin OLTP and Gremlin OLAP. First, Gremlin OLTP (via `Traversal`) leverages a link:http://en.wikipedia.org/wiki/Depth-first_search[depth-first] execution engine. Depth-first execution has a limited memory footprint due to link:http://en.wikipedia.org/wiki/Lazy_evaluation[lazy evaluation]. On the other hand, Gremlin OLAP (via `TraversalVertexProgram`) leverages a link:http://en.wikipedia.org/wiki/Breadth-first_search[breadth-first] execution engine which maintains a larger memory footprint, but a better time complexity due to vertex-local traversers being able to be merged (via "bulking"). The second difference is that Gremlin OLTP is executed in a serial fashion, while Gremlin OLAP is executed in a parallel fashion. These two fundamental differences lead to the behaviors enumerated below.
   
   image::gremlin-without-a-cause.png[width=200,float=right]
   
    . Traversal sideEffects are represented as a distributed data structure across the graph's vertex set. It is not possible to get a global view of a sideEffect until it is aggregated via a <<mapreduce,MapReduce>> job. In some situations, the local vertex representation of the sideEffect is sufficient to ensure the intended semantics of the traversal are respected. However, this is not generally true so be wary of traversals that require global views of a sideEffect.
  - . When evaluating traversals that rely on path information (i.e. the history of the traversal), practical computational limits can be easily reached due the link:http://en.wikipedia.org/wiki/Combinatorial_explosion[combinatoric explosion] of data. With path computing enabled, every traverser is unique and thus, must be enumerated as opposed to being bulked. The difference being a collection of paths vs. a single 64-bit long at a single vertex. For more information on this concept, please see link:http://thinkaurelius.com/2012/11/11/faunus-provides-big-graph-data-analytics/[Faunus Provides Big Graph Data].
  + . When evaluating traversals that rely on path information (i.e. the history of the traversal), practical computational limits can easily be reached due the link:http://en.wikipedia.org/wiki/Combinatorial_explosion[combinatoric explosion] of data. With path computing enabled, every traverser is unique and thus, must be enumerated as opposed to being bulked. The difference being a collection of paths vs. a single 64-bit long at a single vertex. For more information on this concept, please see link:http://thinkaurelius.com/2012/11/11/faunus-provides-big-graph-data-analytics/[Faunus Provides Big Graph Data].
    . When traversals of the form `x.as('a').y.someSideEffectStep('a').z` are evaluated, the `a` sideEffect is stored in the path information of the traverser and thus, such traversals turn on path calculations when executed on a GraphComputer.
  - . Steps that are concerned with the global ordering of traversers do not have a meaningful representation in OLAP. For example, what does <<order-step,`order()`>>-step mean when all traversers are being processed in parallel? Even if the traversers were aggregated and ordered, then at the next step they would return to being executed in parallel and thus, in an unpredictable order. Other steps of this nature include <<orderby-step,`orderby()`>> and <<shuffle-step,`shuffle()`>>. When these steps are executed at the end of a traversal, the `TraverserMapReduce` job ensures the resultant serial representation is ordered accordingly.
  + . Steps that are concerned with the global ordering of traversers do not have a meaningful representation in OLAP. For example, what does <<order-step,`order()`>>-step mean when all traversers are being processed in parallel? Even if the traversers were aggregated and ordered, then at the next step they would return to being executed in parallel and thus, in an unpredictable order. Other steps of this nature include <<orderby-step,`orderby()`>> and <<shuffle-step,`shuffle()`>>. When these steps are executed at the end of a traversal (i.e the final step), the `TraverserMapReduce` job ensures the resultant serial representation is ordered accordingly.
    . Steps that are concerned with providing a global aggregate to the next step of computation do not have a correlate in OLAP. For example, <<fold-step,`fold()`>>-step can only fold up the objects at each executing vertex. Next, even if a global fold was possible, where would it go? Which vertex would be the host of the data structure? The `fold()`-step only makes sense as an end-step whereby a MapReduce job can generate the proper global-to-local data reduction.
positive.code: ==>27=1
  ==>29=3
  
  In the OLAP example above, the traversal is provided to a newly constructed `TraversalVertexProgram` which is (logically) sent to each vertex in the graph. The traversals evaluation requires (logically) 5 BSP iterations and each iteration is interpreted as such:
  
   . `g.V()`: Put a traverser on each vertex in the graph.
   . `both()`: Propagate each traverser to the vertices `both`-adjacent to its current vertex.
  
negative.code:  . `value('age')`: Have all the traversers reference the integer age of their current vertex.
   . `groupCount()`: Count how many times a particular age has been seen.
  
  While 5 iterations were presented, in fact, `TraversalVertexProgram` will execute the traversal in only 3 iterations. The reason being is that `has('age').value('age').groupCount()` can all be executed in a single iteration as any message sent would simply be to the current executing vertex. Thus, a simple optimization exists in Gremlin OLAP called "reflexive message passing" which simulates non-message-passing BSP iterations within a single BSP iteration.
  
  When the computation is complete a <<mapreduce,MapReduce>> job executes which aggregates all the `groupCount()` sideEffect Map (i.e. "`HashMap`") objects on each vertex into a single local representation (thus, turning the distributed Map representation into a local Map representation).
  
  The same OLAP traversal can be executed using the standard `g.compute()` model, though at the expense of verbosity. `TraversalVertexProgram` provides a fluent `Builder` for constructing a `TraversalVertexProgram`. The specified `traversal()` can be either a `Supplier<Traversal>` object, a `Supplier<Traversal>` class, or a link:http://en.wikipedia.org/wiki/Scripting_for_the_Java_Platform[JSR-223] script that will generate (i.e. supply) a `Traversal`. If `traversal()` is supplied a single string, it is assumed that "gremlin-groovy" is the `ScriptEngine` to use. If two strings are supplied, then the first string denotes the `ScriptEngine` to evaluate the second string script with in order to generate (i.e. supply) the `Traversal`.
  
  