You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by jo...@apache.org on 2019/02/25 12:09:18 UTC
[tinkerpop] 01/01: TINKERPOP-2166 Cache expression to obtain the
method in PSerializer
This is an automated email from the ASF dual-hosted git repository.
jorgebg pushed a commit to branch TINKERPOP-2166
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 543a0e222c5247e7d45d44b0803037f3be5c8acd
Author: Jorge Bay Gondra <jo...@gmail.com>
AuthorDate: Mon Feb 25 13:03:45 2019 +0100
TINKERPOP-2166 Cache expression to obtain the method in PSerializer
---
.../driver/ser/binary/types/PSerializer.java | 133 +++++++++++++++------
.../driver/GraphBinaryReaderWriterBenchmark.java | 9 ++
2 files changed, 108 insertions(+), 34 deletions(-)
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/PSerializer.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/PSerializer.java
index 0ae3420..b7c08a0 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/PSerializer.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/PSerializer.java
@@ -27,6 +27,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.P;
import org.apache.tinkerpop.gremlin.process.traversal.util.AndP;
import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
@@ -34,6 +35,8 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
/**
* @author Stephen Mallette (http://stephen.genoprime.com)
@@ -42,6 +45,8 @@ public class PSerializer<T extends P> extends SimpleTypeSerializer<T> {
private final Class<T> classOfP;
+ private final ConcurrentHashMap<PFunctionId, CheckedFunction> methods = new ConcurrentHashMap<>();
+
public PSerializer(final DataType typeOfP, final Class<T> classOfP) {
super(typeOfP);
this.classOfP = classOfP;
@@ -53,59 +58,88 @@ public class PSerializer<T extends P> extends SimpleTypeSerializer<T> {
final int length = context.readValue(buffer, Integer.class, false);
final Object[] args = new Object[length];
final Class<?>[] argumentClasses = new Class[length];
- boolean collectionType = false;
for (int i = 0; i < length; i++) {
args[i] = context.read(buffer);
argumentClasses[i] = args[i].getClass();
}
- switch (predicateName) {
- case "and":
- return (T) ((P) args[0]).and((P) args[1]);
- case "or":
- return (T) ((P) args[0]).or((P) args[1]);
- default:
- Method m;
+ if ("and".equals(predicateName)) {
+ return (T) ((P) args[0]).and((P) args[1]);
+ } else if ("or".equals(predicateName)) {
+ return (T) ((P) args[0]).or((P) args[1]);
+ }
+
+ CheckedFunction<Object[], T> f = getMethod(predicateName, argumentClasses);
+
+ try {
+ return f.apply(args);
+ } catch (Exception ex) {
+ throw new SerializationException(ex);
+ }
+ }
+
+ private CheckedFunction getMethod(final String predicateName, final Class<?>[] argumentClasses) throws SerializationException {
+ final PFunctionId id = new PFunctionId(predicateName, argumentClasses);
+
+ CheckedFunction<Object[], T> result = methods.get(id);
+
+ if (result == null) {
+ boolean collectionType = false;
+ Method m;
+ try {
+ // do a direct lookup
+ m = classOfP.getMethod(predicateName, argumentClasses);
+ } catch (NoSuchMethodException ex0) {
+ // then try collection types
try {
- // do a direct lookup
- m = classOfP.getMethod(predicateName, argumentClasses);
- } catch (NoSuchMethodException ex0) {
- // then try collection types
+ m = classOfP.getMethod(predicateName, Collection.class);
+ collectionType = true;
+ } catch (NoSuchMethodException ex1) {
+ // finally go for the generics
try {
- m = classOfP.getMethod(predicateName, Collection.class);
- collectionType = true;
- } catch (NoSuchMethodException ex1) {
- // finally go for the generics
- try {
- m = classOfP.getMethod(predicateName, Object.class);
- } catch (NoSuchMethodException ex2) {
- throw new SerializationException("not found");
- }
+ m = classOfP.getMethod(predicateName, Object.class);
+ } catch (NoSuchMethodException ex2) {
+ throw new SerializationException("not found");
}
}
+ }
- try {
- if (Modifier.isStatic(m.getModifiers())) {
- if (collectionType)
- return (T) m.invoke(null, Arrays.asList(args));
- else
- return (T) m.invoke(null, args);
+ final Method finalMethod = m;
+
+ try {
+ if (Modifier.isStatic(m.getModifiers())) {
+ if (collectionType) {
+ result = (args) -> (T) finalMethod.invoke(null, Arrays.asList(args));
} else {
- // try an instance method as it might be a form of ConnectiveP which means there is a P as an
- // argument that should be used as the object of an instance method
- if (args.length != 2 || !(args[0] instanceof P) || !(args[1] instanceof P))
+ result = (args) -> (T) finalMethod.invoke(null, args);
+ }
+ } else {
+ // try an instance method as it might be a form of ConnectiveP which means there is a P as an
+ // argument that should be used as the object of an instance method
+ if (argumentClasses.length != 2) {
+ throw new IllegalStateException(String.format("Could not determine the form of P for %s and %s",
+ predicateName, Arrays.asList(argumentClasses)));
+ }
+
+ result = (args) -> {
+ if (!(args[0] instanceof P) || !(args[1] instanceof P))
throw new IllegalStateException(String.format("Could not determine the form of P for %s and %s",
predicateName, Arrays.asList(args)));
final P firstP = (P) args[0];
final P secondP = (P) args[1];
- return (T) m.invoke(firstP, secondP);
- }
- } catch (Exception ex) {
- throw new SerializationException(ex);
+ return (T) finalMethod.invoke(firstP, secondP);
+ };
}
+
+ methods.put(id, result);
+ } catch (Exception ex) {
+ throw new SerializationException(ex);
+ }
}
+
+ return result;
}
@Override
@@ -127,4 +161,35 @@ public class PSerializer<T extends P> extends SimpleTypeSerializer<T> {
context.write(o, buffer);
}
}
+
+ @FunctionalInterface
+ interface CheckedFunction<A, R> {
+ R apply(A t) throws InvocationTargetException, IllegalAccessException;
+ }
+
+ class PFunctionId {
+ private final String predicateName;
+ private final Class<?>[] argumentClasses;
+
+ PFunctionId(final String predicateName, final Class<?>[] argumentClasses) {
+ this.predicateName = predicateName;
+ this.argumentClasses = argumentClasses;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ PFunctionId that = (PFunctionId) o;
+ return predicateName.equals(that.predicateName) &&
+ Arrays.equals(argumentClasses, that.argumentClasses);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Objects.hash(predicateName);
+ result = 31 * result + Arrays.hashCode(argumentClasses);
+ return result;
+ }
+ }
}
diff --git a/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/driver/GraphBinaryReaderWriterBenchmark.java b/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/driver/GraphBinaryReaderWriterBenchmark.java
index 1cc509a..d0692b7 100644
--- a/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/driver/GraphBinaryReaderWriterBenchmark.java
+++ b/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/driver/GraphBinaryReaderWriterBenchmark.java
@@ -25,6 +25,7 @@ import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
import org.apache.tinkerpop.gremlin.driver.ser.binary.GraphBinaryReader;
import org.apache.tinkerpop.gremlin.driver.ser.binary.GraphBinaryWriter;
import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
import org.openjdk.jmh.annotations.Benchmark;
@@ -53,6 +54,7 @@ public class GraphBinaryReaderWriterBenchmark extends AbstractBenchmarkBase {
public static class BenchmarkState {
public ByteBuf bytecodeBuffer1 = allocator.buffer(2048);
public ByteBuf bytecodeBuffer2 = allocator.buffer(2048);
+ public ByteBuf pBuffer1 = allocator.buffer(2048);
public final Bytecode bytecode1 = new Bytecode();
public ByteBuf bufferWrite = allocator.buffer(2048);
@@ -79,12 +81,14 @@ public class GraphBinaryReaderWriterBenchmark extends AbstractBenchmarkBase {
writer.writeValue(bytecode1, bytecodeBuffer1, false);
writer.writeValue(bytecode2, bytecodeBuffer2, false);
+ writer.writeValue(P.between(1, 2), pBuffer1, false);
}
@Setup(Level.Invocation)
public void setupInvocation() {
bytecodeBuffer1.readerIndex(0);
bytecodeBuffer2.readerIndex(0);
+ pBuffer1.readerIndex(0);
bufferWrite.readerIndex(0);
bufferWrite.writerIndex(0);
}
@@ -116,4 +120,9 @@ public class GraphBinaryReaderWriterBenchmark extends AbstractBenchmarkBase {
public void readBytecode2(BenchmarkState state) throws SerializationException {
reader.readValue(state.bytecodeBuffer2, Bytecode.class, false);
}
+
+ @Benchmark
+ public void readP1(BenchmarkState state) throws SerializationException {
+ reader.readValue(state.pBuffer1, P.class, false);
+ }
}