You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2017/05/23 20:59:37 UTC

[2/2] tinkerpop git commit: TINKERPOP-1676 Improved speed and memory usage of GraphSON

TINKERPOP-1676 Improved speed and memory usage of GraphSON

This change is specific to TinkerGraph and the serialization of vertices/edges/properties. Removed a "middle layer" of JSON to Object serialization which was coercing JSON to Map first and then converting that to the graph elements. Also made deserializers cacheable.


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

Branch: refs/heads/TINKERPOP-1676
Commit: b1870c225f971792ce61f417537f6f7b71bbc011
Parents: deb2fec
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Tue May 23 16:57:12 2017 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Tue May 23 16:57:12 2017 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |   1 +
 .../io/graphson/AbstractObjectDeserializer.java |   5 +
 .../io/graphson/GraphSONSerializersV2d0.java    | 164 +++++++++++++++----
 .../structure/TinkerIoRegistryV2d0.java         |   5 +
 4 files changed, 145 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b1870c22/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 1f89598..3ff6cea 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.2.5 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* Improved performance and memory usage of GraphSON when serializing `TinkerGraph` and graph elements.
 * Removed use of `stream()` in `DetachedEdge` and `DetachedVertex`.
 * Deprecated a constructor in `DetachedEdge` that made use of `Pair` in favor of a new one that just uses the objects that were in the `Pair`.
 * Reduced memory usage for TinkerGraph deserialization in GraphSON by streaming vertices and edges.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b1870c22/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/AbstractObjectDeserializer.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/AbstractObjectDeserializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/AbstractObjectDeserializer.java
index bd7f4b6..9e4e102 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/AbstractObjectDeserializer.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/AbstractObjectDeserializer.java
@@ -47,5 +47,10 @@ public abstract class AbstractObjectDeserializer<T> extends StdDeserializer<T> {
         return createObject(mapData);
     }
 
+    @Override
+    public boolean isCachable() {
+        return true;
+    }
+
     public abstract T createObject(final Map<String, Object> data);
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b1870c22/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializersV2d0.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializersV2d0.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializersV2d0.java
index 9a27279..0008d3a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializersV2d0.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializersV2d0.java
@@ -43,7 +43,9 @@ import org.apache.tinkerpop.shaded.jackson.core.JsonGenerationException;
 import org.apache.tinkerpop.shaded.jackson.core.JsonGenerator;
 import org.apache.tinkerpop.shaded.jackson.core.JsonParser;
 import org.apache.tinkerpop.shaded.jackson.core.JsonProcessingException;
+import org.apache.tinkerpop.shaded.jackson.core.JsonToken;
 import org.apache.tinkerpop.shaded.jackson.databind.DeserializationContext;
+import org.apache.tinkerpop.shaded.jackson.databind.JavaType;
 import org.apache.tinkerpop.shaded.jackson.databind.SerializerProvider;
 import org.apache.tinkerpop.shaded.jackson.databind.deser.std.StdDeserializer;
 import org.apache.tinkerpop.shaded.jackson.databind.jsontype.TypeSerializer;
@@ -416,52 +418,117 @@ class GraphSONSerializersV2d0 {
 
     //////////////////////////// DESERIALIZERS ///////////////////////////
 
-
-    static class VertexJacksonDeserializer extends AbstractObjectDeserializer<Vertex> {
+    static class VertexJacksonDeserializer extends StdDeserializer<Vertex> {
 
         public VertexJacksonDeserializer() {
             super(Vertex.class);
         }
 
+        public Vertex deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+            final JavaType propertiesType = deserializationContext.getConfig().getTypeFactory().constructMapType(HashMap.class, String.class, Object.class);
+
+            Object id = null;
+            String label = null;
+            Map<String, Object> properties = null;
+            while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
+                if (jsonParser.getCurrentName().equals(GraphSONTokens.ID)) {
+                    jsonParser.nextToken();
+                    id = deserializationContext.readValue(jsonParser, Object.class);
+                } else if (jsonParser.getCurrentName().equals(GraphSONTokens.LABEL)) {
+                    jsonParser.nextToken();
+                    label = jsonParser.getText();
+                } else if (jsonParser.getCurrentName().equals(GraphSONTokens.PROPERTIES)) {
+                    jsonParser.nextToken();
+                    properties = deserializationContext.readValue(jsonParser, propertiesType);
+                }
+            }
+
+            return new DetachedVertex(id, label, properties);
+        }
+
         @Override
-        public Vertex createObject(final Map<String, Object> vertexData) {
-            return new DetachedVertex(
-                    vertexData.get(GraphSONTokens.ID),
-                    vertexData.get(GraphSONTokens.LABEL).toString(),
-                    (Map<String, Object>) vertexData.get(GraphSONTokens.PROPERTIES)
-            );
+        public boolean isCachable() {
+            return true;
         }
     }
 
-    static class EdgeJacksonDeserializer extends AbstractObjectDeserializer<Edge> {
+    static class EdgeJacksonDeserializer extends StdDeserializer<Edge> {
 
         public EdgeJacksonDeserializer() {
             super(Edge.class);
         }
 
         @Override
-        public Edge createObject(final Map<String, Object> edgeData) {
-            return new DetachedEdge(
-                    edgeData.get(GraphSONTokens.ID),
-                    edgeData.get(GraphSONTokens.LABEL).toString(),
-                    (Map) edgeData.get(GraphSONTokens.PROPERTIES),
-                    Pair.with(edgeData.get(GraphSONTokens.OUT), edgeData.get(GraphSONTokens.OUT_LABEL).toString()),
-                    Pair.with(edgeData.get(GraphSONTokens.IN), edgeData.get(GraphSONTokens.IN_LABEL).toString())
-            );
+        public Edge deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+            final JavaType propertiesType = deserializationContext.getConfig().getTypeFactory().constructMapType(HashMap.class, String.class, Object.class);
+
+            Object id = null;
+            String label = null;
+            Object outVId = null;
+            String outVLabel = null;
+            Object inVId = null;
+            String inVLabel = null;
+            Map<String, Object> properties = null;
+            while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
+                if (jsonParser.getCurrentName().equals(GraphSONTokens.ID)) {
+                    jsonParser.nextToken();
+                    id = deserializationContext.readValue(jsonParser, Object.class);
+                } else if (jsonParser.getCurrentName().equals(GraphSONTokens.LABEL)) {
+                    jsonParser.nextToken();
+                    label = jsonParser.getText();
+                } else if (jsonParser.getCurrentName().equals(GraphSONTokens.OUT)) {
+                    jsonParser.nextToken();
+                    outVId = deserializationContext.readValue(jsonParser, Object.class);
+                } else if (jsonParser.getCurrentName().equals(GraphSONTokens.OUT_LABEL)) {
+                    jsonParser.nextToken();
+                    outVLabel = jsonParser.getText();
+                } else if (jsonParser.getCurrentName().equals(GraphSONTokens.IN)) {
+                    jsonParser.nextToken();
+                    inVId = deserializationContext.readValue(jsonParser, Object.class);
+                } else if (jsonParser.getCurrentName().equals(GraphSONTokens.IN_LABEL)) {
+                    jsonParser.nextToken();
+                    inVLabel = jsonParser.getText();
+                } else if (jsonParser.getCurrentName().equals(GraphSONTokens.PROPERTIES)) {
+                    jsonParser.nextToken();
+                    properties = deserializationContext.readValue(jsonParser, propertiesType);
+                }
+            }
+
+            return new DetachedEdge(id, label, properties, outVId, outVLabel, inVId, inVLabel);
+        }
+
+        @Override
+        public boolean isCachable() {
+            return true;
         }
     }
 
-    static class PropertyJacksonDeserializer extends AbstractObjectDeserializer<Property> {
+    static class PropertyJacksonDeserializer extends StdDeserializer<Property> {
 
         public PropertyJacksonDeserializer() {
             super(Property.class);
         }
 
         @Override
-        public Property createObject(final Map<String, Object> propData) {
-            return new DetachedProperty(
-                    (String) propData.get(GraphSONTokens.KEY),
-                    propData.get(GraphSONTokens.VALUE));
+        public Property deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+            String key = null;
+            Object value = null;
+            while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
+                if (jsonParser.getCurrentName().equals(GraphSONTokens.KEY)) {
+                    jsonParser.nextToken();
+                    key = jsonParser.getText();
+                } else if (jsonParser.getCurrentName().equals(GraphSONTokens.VALUE)) {
+                    jsonParser.nextToken();
+                    value = deserializationContext.readValue(jsonParser, Object.class);
+                }
+            }
+
+            return new DetachedProperty<>(key, value);
+        }
+
+        @Override
+        public boolean isCachable() {
+            return true;
         }
     }
 
@@ -485,20 +552,42 @@ class GraphSONSerializersV2d0 {
         }
     }
 
-    static class VertexPropertyJacksonDeserializer extends AbstractObjectDeserializer<VertexProperty> {
+    static class VertexPropertyJacksonDeserializer extends StdDeserializer<VertexProperty> {
 
         protected VertexPropertyJacksonDeserializer() {
             super(VertexProperty.class);
         }
 
         @Override
-        public VertexProperty createObject(final Map<String, Object> propData) {
-            return new DetachedVertexProperty(
-                    propData.get(GraphSONTokens.ID),
-                    (String) propData.get(GraphSONTokens.LABEL),
-                    propData.get(GraphSONTokens.VALUE),
-                    (Map) propData.get(GraphSONTokens.PROPERTIES)
-            );
+        public VertexProperty deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+            final JavaType propertiesType = deserializationContext.getConfig().getTypeFactory().constructMapType(HashMap.class, String.class, Object.class);
+
+            Object id = null;
+            String label = null;
+            Object value = null;
+            Map<String, Object> properties = null;
+            while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
+                if (jsonParser.getCurrentName().equals(GraphSONTokens.ID)) {
+                    jsonParser.nextToken();
+                    id = deserializationContext.readValue(jsonParser, Object.class);
+                } else if (jsonParser.getCurrentName().equals(GraphSONTokens.LABEL)) {
+                    jsonParser.nextToken();
+                    label = jsonParser.getText();
+                } else if (jsonParser.getCurrentName().equals(GraphSONTokens.VALUE)) {
+                    jsonParser.nextToken();
+                    value = deserializationContext.readValue(jsonParser, Object.class);
+                }else if (jsonParser.getCurrentName().equals(GraphSONTokens.PROPERTIES)) {
+                    jsonParser.nextToken();
+                    properties = deserializationContext.readValue(jsonParser, propertiesType);
+                }
+            }
+
+            return new DetachedVertexProperty<>(id, label, value, properties);
+        }
+
+        @Override
+        public boolean isCachable() {
+            return true;
         }
     }
 
@@ -555,6 +644,11 @@ class GraphSONSerializersV2d0 {
             }
             return t;
         }
+
+        @Override
+        public boolean isCachable() {
+            return true;
+        }
     }
 
     static class IntegerJackonsDeserializer extends StdDeserializer<Integer> {
@@ -567,6 +661,11 @@ class GraphSONSerializersV2d0 {
         public Integer deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
             return jsonParser.getIntValue();
         }
+
+        @Override
+        public boolean isCachable() {
+            return true;
+        }
     }
 
     static class DoubleJackonsDeserializer extends StdDeserializer<Double> {
@@ -579,6 +678,11 @@ class GraphSONSerializersV2d0 {
         public Double deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
             return jsonParser.getDoubleValue();
         }
+
+        @Override
+        public boolean isCachable() {
+            return true;
+        }
     }
 }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b1870c22/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV2d0.java
----------------------------------------------------------------------
diff --git a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV2d0.java b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV2d0.java
index 394216b..280d1af 100644
--- a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV2d0.java
+++ b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerIoRegistryV2d0.java
@@ -218,5 +218,10 @@ public final class TinkerIoRegistryV2d0 extends AbstractIoRegistry {
 
             return graph;
         }
+
+        @Override
+        public boolean isCachable() {
+            return true;
+        }
     }
 }