TINKERPOP-1950 Cached global strategy lookups during traversal construction

This change leads to a 1.5x to 2x speed improvement in traversal construction. 
It is especially effective when processing traversals that have many child 
traversals within them as this method is called for not only the parent 
traversal but all the children as well.


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

Branch: refs/heads/TINKERPOP-1950
Commit: 4fa21313bd4647015072b59ec3ba2d7bfb5c665d
Parents: 8462f85
Author: Stephen Mallette <[email protected]>
Authored: Fri Apr 20 16:18:13 2018 -0400
Committer: Stephen Mallette <[email protected]>
Committed: Tue Apr 24 18:50:01 2018 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 .../process/traversal/TraversalStrategies.java  | 29 ++++++++++++++------
 2 files changed, 22 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4fa21313/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 51c9f68..ea7473b 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -25,6 +25,7 @@ 
image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 
 * Bumped to httpclient 4.5.5.
 * Improved performance of GraphSON deserialization of `Bytecode`.
+* Improved performance of traversal construction.
 
 [[release-3-2-8]]
 === TinkerPop 3.2.8 (Release Date: April 2, 2018)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4fa21313/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
----------------------------------------------------------------------
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
index c7ee5bf..7ca5b61 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
@@ -63,6 +63,8 @@ import java.util.stream.Collectors;
  */
 public interface TraversalStrategies extends Serializable, Cloneable {
 
+    static Set<Class> LOADED = new HashSet<>();
+
     static List<Class<? extends TraversalStrategy>> STRATEGY_CATEGORIES = 
Collections.unmodifiableList(Arrays.asList(TraversalStrategy.DecorationStrategy.class,
 TraversalStrategy.OptimizationStrategy.class, 
TraversalStrategy.ProviderOptimizationStrategy.class, 
TraversalStrategy.FinalizationStrategy.class, 
TraversalStrategy.VerificationStrategy.class));
 
     /**
@@ -244,20 +246,31 @@ public interface TraversalStrategies extends 
Serializable, Cloneable {
         public static TraversalStrategies getStrategies(final Class 
graphOrGraphComputerClass) {
             try {
                 // be sure to load the class so that its static{} traversal 
strategy registration component is loaded.
-                // this is more important for GraphComputer classes as they 
are typically not instantiated prior to strategy usage like Graph classes.
-                final String graphComputerClassName = null != 
graphOrGraphComputerClass.getDeclaringClass() ?
+                // this is more important for GraphComputer classes as they 
are typically not instantiated prior to
+                // strategy usage like Graph classes.
+                if (!LOADED.contains(graphOrGraphComputerClass)) {
+                    final String graphComputerClassName = null != 
graphOrGraphComputerClass.getDeclaringClass() ?
                         
graphOrGraphComputerClass.getCanonicalName().replace("." + 
graphOrGraphComputerClass.getSimpleName(), "$" + 
graphOrGraphComputerClass.getSimpleName()) :
                         graphOrGraphComputerClass.getCanonicalName();
-                Class.forName(graphComputerClassName);
+                    Class.forName(graphComputerClassName);
+
+                    // keep track of stuff we already loaded once - stuff in 
this if/statement isn't cheap and this
+                    // method gets called a lot, basically every time a new 
traversal gets spun up (that includes
+                    // child traversals.
+                    LOADED.add(graphOrGraphComputerClass);
+                }
             } catch (final ClassNotFoundException e) {
                 throw new IllegalStateException(e.getMessage(), e);
             }
-            if (Graph.class.isAssignableFrom(graphOrGraphComputerClass)) {
-                final TraversalStrategies traversalStrategies = 
GRAPH_CACHE.get(graphOrGraphComputerClass);
-                return null == traversalStrategies ? 
GRAPH_CACHE.get(Graph.class) : traversalStrategies;
+            
+            if (GRAPH_CACHE.containsKey(graphOrGraphComputerClass)) {
+                return GRAPH_CACHE.get(graphOrGraphComputerClass);
+            } else if 
(Graph.class.isAssignableFrom(graphOrGraphComputerClass)) {
+                return GRAPH_CACHE.get(Graph.class);
+            } else if 
(GRAPH_COMPUTER_CACHE.containsKey(graphOrGraphComputerClass)) {
+                return GRAPH_COMPUTER_CACHE.get(graphOrGraphComputerClass);
             } else if 
(GraphComputer.class.isAssignableFrom(graphOrGraphComputerClass)) {
-                final TraversalStrategies traversalStrategies = 
GRAPH_COMPUTER_CACHE.get(graphOrGraphComputerClass);
-                return null == traversalStrategies ? 
GRAPH_COMPUTER_CACHE.get(GraphComputer.class) : traversalStrategies;
+                return GRAPH_COMPUTER_CACHE.get(GraphComputer.class);
             } else {
                 throw new IllegalArgumentException("The 
TraversalStrategies.GlobalCache only supports Graph and GraphComputer strategy 
caching: " + graphOrGraphComputerClass.getCanonicalName());
             }

Reply via email to