This is an automated email from the ASF dual-hosted git repository. jorgebg pushed a commit to branch TINKERPOP-1942 in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
The following commit(s) were added to refs/heads/TINKERPOP-1942 by this push: new c66c2f6 TINKERPOP-1942 Basic implementation and benchmarks c66c2f6 is described below commit c66c2f6b6f56752a7b34e2445afdcca98bf5496c Author: Jorge Bay Gondra <jorgebaygon...@gmail.com> AuthorDate: Fri Oct 26 16:11:52 2018 +0200 TINKERPOP-1942 Basic implementation and benchmarks --- .../gremlin/driver/ser/GraphBinarySerializer.java | 52 +++++++++ .../gremlin/driver/ser/binary/DataType.java | 80 +++++++++++++ .../driver/ser/binary/GraphBinaryReader.java | 56 ++++++++++ .../gremlin/driver/ser/binary/TypeSerializer.java | 36 ++++++ .../driver/ser/binary/TypeSerializerRegistry.java | 70 ++++++++++++ .../ser/binary/types/ByteCodeSerializer.java | 53 +++++++++ .../driver/ser/binary/types/MapSerializer.java | 40 +++++++ .../ser/binary/types/RequestMessageSerializer.java | 53 +++++++++ .../ser/binary/types/SimpleTypeSerializer.java | 36 ++++++ .../ser/binary/types/SingleTypeSerializer.java | 43 +++++++ .../driver/ser/binary/types/StringSerializer.java | 34 ++++++ .../driver/ser/binary/types/UUIDSerializer.java | 32 ++++++ gremlin-tools/gremlin-benchmark/pom.xml | 5 + .../gremlin/driver/SerializationBenchmark.java | 124 +++++++++++++++++++++ 14 files changed, 714 insertions(+) diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphBinarySerializer.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphBinarySerializer.java new file mode 100644 index 0000000..7d4b768 --- /dev/null +++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/GraphBinarySerializer.java @@ -0,0 +1,52 @@ +/* + * 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.driver.ser; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import org.apache.tinkerpop.gremlin.driver.message.RequestMessage; +import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage; + +public class GraphBinarySerializer extends AbstractMessageSerializer { + @Override + public ByteBuf serializeResponseAsBinary(ResponseMessage responseMessage, ByteBufAllocator allocator) throws SerializationException { + return null; + } + + @Override + public ByteBuf serializeRequestAsBinary(RequestMessage requestMessage, ByteBufAllocator allocator) throws SerializationException { + return null; + } + + @Override + public RequestMessage deserializeRequest(ByteBuf msg) throws SerializationException { + //TODO: Use BinaryReader + return null; + } + + @Override + public ResponseMessage deserializeResponse(ByteBuf msg) throws SerializationException { + return null; + } + + @Override + public String[] mimeTypesSupported() { + return new String[0]; + } +} diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/DataType.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/DataType.java new file mode 100644 index 0000000..acd1a80 --- /dev/null +++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/DataType.java @@ -0,0 +1,80 @@ +/* + * 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.driver.ser.binary; + +import java.util.HashMap; +import java.util.Map; + +public enum DataType { + INT(0x01), + LONG(0x02), + STRING(0X03), + DATE(0X04), + TIMESTAMP(0X05), + CLASS(0X06), + DOUBLE(0X07), + FLOAT(0X08), + LIST(0X09), + MAP(0X0A), + SET(0X0B), + UUID(0X0C), + EDGE(0X0D), + PATH(0X0E), + PROPERTY(0X0F), + TINKERGRAPH(0X10), + VERTEX(0X11), + VERTEXPROPERTY(0X12), + BARRIER(0X13), + BINDING(0X14), + BYTECODE(0X15); + + private final int code; + private static final Map<Integer, DataType> typeByCode = new HashMap<>(); + + static { + for (DataType t : DataType.values()) { + typeByCode.put(t.code, t); + } + } + + DataType(int code) { + this.code = code; + } + + /** + * Gets the data type code. + */ + public int getCode() { + return code; + } + + /** + * Gets the data type code. + */ + public byte getCodeByte() { + return (byte)code; + } + + /** + * Gets a DataType by code. + */ + public static DataType get(int code) { + return typeByCode.get(code); + } +} diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/GraphBinaryReader.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/GraphBinaryReader.java new file mode 100644 index 0000000..cc3fcdb --- /dev/null +++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/GraphBinaryReader.java @@ -0,0 +1,56 @@ +/* + * 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.driver.ser.binary; + +import io.netty.buffer.ByteBuf; +import org.apache.tinkerpop.gremlin.driver.ser.SerializationException; + +public class GraphBinaryReader { + private final TypeSerializerRegistry registry; + + public GraphBinaryReader() { + registry = TypeSerializerRegistry.INSTANCE; + } + + /** + * Reads a value for an specific type. + * @throws SerializationException + */ + public <T> T readValue(ByteBuf buffer, Class<T> type) throws SerializationException { + if(buffer == null) { + throw new IllegalArgumentException("input cannot be null."); + } else if(type == null) { + throw new IllegalArgumentException("type cannot be null."); + } + + TypeSerializer<T> serializer = registry.getSerializer(type); + return serializer.readValue(buffer, this); + } + + /** + * Reads the type information and value of a given buffer from fully qualified format. + * @throws SerializationException + */ + public <T> T readFullyQualifiedObject(ByteBuf buffer) throws SerializationException { + // Fully-qualified format: {type_code}{type_info}{value_flag}{value} + DataType type = DataType.get(buffer.readByte()); + TypeSerializer<T> serializer = registry.getSerializer(type); + return serializer.read(buffer, this); + } +} diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/TypeSerializer.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/TypeSerializer.java new file mode 100644 index 0000000..afeb701 --- /dev/null +++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/TypeSerializer.java @@ -0,0 +1,36 @@ +/* + * 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.driver.ser.binary; + +import io.netty.buffer.ByteBuf; +import org.apache.tinkerpop.gremlin.driver.ser.SerializationException; + +public interface TypeSerializer<T> { + /** + * Reads the type information and value from the buffer and returns an instance of T. + */ + T read(ByteBuf buffer, GraphBinaryReader context) throws SerializationException; + + /** + * Reads the value from the buffer (not the type information) and returns an instance of T. + * <p>Implementors should throw an exception when a complex type doesn't support </p> + */ + T readValue(ByteBuf buffer, GraphBinaryReader context) throws SerializationException; + +} diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/TypeSerializerRegistry.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/TypeSerializerRegistry.java new file mode 100644 index 0000000..ef59197 --- /dev/null +++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/TypeSerializerRegistry.java @@ -0,0 +1,70 @@ +/* + * 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.driver.ser.binary; + +import org.apache.tinkerpop.gremlin.driver.message.RequestMessage; +import org.apache.tinkerpop.gremlin.driver.ser.binary.types.*; +import org.apache.tinkerpop.gremlin.process.traversal.Bytecode; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class TypeSerializerRegistry { + public static final TypeSerializerRegistry INSTANCE = new TypeSerializerRegistry(); + + private final Map<Class<?>, TypeSerializer<?>> serializers = new HashMap<>(); + private final Map<DataType, TypeSerializer<?>> serializersByDataType = new HashMap<>(); + + private TypeSerializerRegistry() { + // No DataType as RequestMessage can't be fully qualified + put(RequestMessage.class, null, new RequestMessageSerializer()); + + put(String.class, DataType.STRING, new StringSerializer()); + put(UUID.class, DataType.UUID, new UUIDSerializer()); + put(Map.class, DataType.MAP, new MapSerializer()); + + put(Integer.class, DataType.INT, SingleTypeSerializer.IntSerializer); + put(Long.class, DataType.LONG, SingleTypeSerializer.LongSerializer); + put(Double.class, DataType.DOUBLE, SingleTypeSerializer.DoubleSerializer); + put(Float.class, DataType.FLOAT, SingleTypeSerializer.FloatSerializer); + + put(Bytecode.class, DataType.BYTECODE, new ByteCodeSerializer()); + } + + public <T> TypeSerializerRegistry put(Class<T> type, DataType dataType, TypeSerializer<T> instance) { + serializers.put(type, instance); + + if (dataType != null) { + serializersByDataType.put(dataType, instance); + } + + return this; + } + + public <T> TypeSerializer<T> getSerializer(Class<T> type) { + //TODO: Check null + return (TypeSerializer<T>) serializers.get(type); + } + + public <T> TypeSerializer<T> getSerializer(DataType dataType) { + //TODO: Check null + return (TypeSerializer<T>) serializersByDataType.get(dataType); + } +} diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/ByteCodeSerializer.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/ByteCodeSerializer.java new file mode 100644 index 0000000..301edcd --- /dev/null +++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/ByteCodeSerializer.java @@ -0,0 +1,53 @@ +/* + * 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.driver.ser.binary.types; + +import io.netty.buffer.ByteBuf; +import org.apache.tinkerpop.gremlin.driver.ser.SerializationException; +import org.apache.tinkerpop.gremlin.driver.ser.binary.GraphBinaryReader; +import org.apache.tinkerpop.gremlin.process.traversal.Bytecode; + +public class ByteCodeSerializer extends SimpleTypeSerializer<Bytecode> { + + @Override + public Bytecode readValue(ByteBuf buffer, GraphBinaryReader context) throws SerializationException { + final Bytecode result = new Bytecode(); + + final int stepsLength = buffer.readInt(); + for (int i = 0; i < stepsLength; i++) { + result.addStep(context.readValue(buffer, String.class), getValues(buffer, context)); + } + + final int sourcesLength = buffer.readInt(); + for (int i = 0; i < sourcesLength; i++) { + result.addSource(context.readValue(buffer, String.class), getValues(buffer, context)); + } + + return result; + } + + private static Object[] getValues(ByteBuf buffer, GraphBinaryReader context) throws SerializationException { + final int valuesLength = buffer.readInt(); + Object[] values = new Object[valuesLength]; + for (int j = 0; j < valuesLength; j++) { + values[j] = context.readFullyQualifiedObject(buffer); + } + return values; + } +} diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/MapSerializer.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/MapSerializer.java new file mode 100644 index 0000000..a9b3ad7 --- /dev/null +++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/MapSerializer.java @@ -0,0 +1,40 @@ +/* + * 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.driver.ser.binary.types; + +import io.netty.buffer.ByteBuf; +import org.apache.tinkerpop.gremlin.driver.ser.SerializationException; +import org.apache.tinkerpop.gremlin.driver.ser.binary.GraphBinaryReader; + +import java.util.HashMap; +import java.util.Map; + +public class MapSerializer extends SimpleTypeSerializer<Map> { + @Override + public Map readValue(ByteBuf buffer, GraphBinaryReader context) throws SerializationException { + final Long length = buffer.readUnsignedInt(); + + Map result = new HashMap<>(); + for (int i = 0; i < length; i++) { + result.put(context.readFullyQualifiedObject(buffer), context.readFullyQualifiedObject(buffer)); + } + + return result; + } +} diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/RequestMessageSerializer.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/RequestMessageSerializer.java new file mode 100644 index 0000000..2511f3a --- /dev/null +++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/RequestMessageSerializer.java @@ -0,0 +1,53 @@ +/* + * 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.driver.ser.binary.types; + +import io.netty.buffer.ByteBuf; +import org.apache.tinkerpop.gremlin.driver.message.RequestMessage; +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.TypeSerializer; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class RequestMessageSerializer implements TypeSerializer<RequestMessage> { + public RequestMessage readValue(ByteBuf buffer, GraphBinaryReader context) throws SerializationException { + final byte version = buffer.readByte(); + assert version >>> 7 == 1; + + final UUID id = context.readValue(buffer, UUID.class); + final String op = context.readValue(buffer, String.class); + final String processor = context.readValue(buffer, String.class); + + final RequestMessage.Builder builder = RequestMessage.build(op).overrideRequestId(id).processor(processor); + + final Map<String, Object> args = context.readValue(buffer, Map.class); + args.forEach(builder::addArg); + + return builder.create(); + } + + @Override + public RequestMessage read(ByteBuf buffer, GraphBinaryReader context) throws SerializationException { + // There is no type code / information for the request message itself. + throw new SerializationException("RequestMessageSerializer must not invoked with type information"); + } +} diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/SimpleTypeSerializer.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/SimpleTypeSerializer.java new file mode 100644 index 0000000..cc7abd3 --- /dev/null +++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/SimpleTypeSerializer.java @@ -0,0 +1,36 @@ +/* + * 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.driver.ser.binary.types; + +import io.netty.buffer.ByteBuf; +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.TypeSerializer; + +public abstract class SimpleTypeSerializer<T> implements TypeSerializer<T> { + @Override + public T read(ByteBuf buffer, GraphBinaryReader context) throws SerializationException { + // No {type_info}, just {value_flag}{value} + final byte valueFlag = buffer.readByte(); + if ((valueFlag & 1) == 1) { + return null; + } + return readValue(buffer, context); + } +} diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/SingleTypeSerializer.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/SingleTypeSerializer.java new file mode 100644 index 0000000..d8e0e0a --- /dev/null +++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/SingleTypeSerializer.java @@ -0,0 +1,43 @@ +/* + * 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.driver.ser.binary.types; + +import io.netty.buffer.ByteBuf; +import org.apache.tinkerpop.gremlin.driver.ser.SerializationException; +import org.apache.tinkerpop.gremlin.driver.ser.binary.GraphBinaryReader; +import java.util.function.Function; + +public class SingleTypeSerializer<T> extends SimpleTypeSerializer<T> { + public static final SingleTypeSerializer<Integer> IntSerializer = new SingleTypeSerializer<>(ByteBuf::readInt); + public static final SingleTypeSerializer<Long> LongSerializer = new SingleTypeSerializer<>(ByteBuf::readLong); + public static final SingleTypeSerializer<Double> DoubleSerializer = new SingleTypeSerializer<>(ByteBuf::readDouble); + public static final SingleTypeSerializer<Float> FloatSerializer = new SingleTypeSerializer<>(ByteBuf::readFloat); + + private final Function<ByteBuf, T> func; + + + public SingleTypeSerializer(Function<ByteBuf, T> func) { + this.func = func; + } + + @Override + public T readValue(ByteBuf buffer, GraphBinaryReader context) throws SerializationException { + return func.apply(buffer); + } +} diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/StringSerializer.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/StringSerializer.java new file mode 100644 index 0000000..b0d5d84 --- /dev/null +++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/StringSerializer.java @@ -0,0 +1,34 @@ +/* + * 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.driver.ser.binary.types; + +import io.netty.buffer.ByteBuf; +import org.apache.tinkerpop.gremlin.driver.ser.SerializationException; +import org.apache.tinkerpop.gremlin.driver.ser.binary.GraphBinaryReader; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +public class StringSerializer extends SimpleTypeSerializer<String> { + @Override + public String readValue(ByteBuf buffer, GraphBinaryReader context) throws SerializationException { + final int length = buffer.readInt(); + return buffer.readCharSequence(length, StandardCharsets.UTF_8).toString(); + } +} diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/UUIDSerializer.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/UUIDSerializer.java new file mode 100644 index 0000000..ca7fbce --- /dev/null +++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/UUIDSerializer.java @@ -0,0 +1,32 @@ +/* + * 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.driver.ser.binary.types; + +import io.netty.buffer.ByteBuf; +import org.apache.tinkerpop.gremlin.driver.ser.SerializationException; +import org.apache.tinkerpop.gremlin.driver.ser.binary.GraphBinaryReader; + +import java.util.UUID; + +public class UUIDSerializer extends SimpleTypeSerializer<UUID> { + @Override + public UUID readValue(ByteBuf buffer, GraphBinaryReader context) throws SerializationException { + return new UUID(buffer.readLong(), buffer.readLong()); + } +} \ No newline at end of file diff --git a/gremlin-tools/gremlin-benchmark/pom.xml b/gremlin-tools/gremlin-benchmark/pom.xml index f3c4c20..2aa3525 100644 --- a/gremlin-tools/gremlin-benchmark/pom.xml +++ b/gremlin-tools/gremlin-benchmark/pom.xml @@ -55,6 +55,11 @@ limitations under the License. <version>${project.version}</version> </dependency> <dependency> + <groupId>org.apache.tinkerpop</groupId> + <artifactId>gremlin-driver</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> <groupId>org.openjdk.jmh</groupId> <artifactId>jmh-core</artifactId> <version>${jmh.version}</version> diff --git a/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/driver/SerializationBenchmark.java b/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/driver/SerializationBenchmark.java new file mode 100644 index 0000000..4347b90 --- /dev/null +++ b/gremlin-tools/gremlin-benchmark/src/main/java/org/apache/tinkerpop/gremlin/driver/SerializationBenchmark.java @@ -0,0 +1,124 @@ +/* + * 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.driver; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import org.apache.tinkerpop.benchmark.util.AbstractBenchmarkBase; +import org.apache.tinkerpop.gremlin.driver.message.RequestMessage; +import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0; +import org.apache.tinkerpop.gremlin.driver.ser.SerializationException; +import org.apache.tinkerpop.gremlin.driver.ser.binary.DataType; +import org.apache.tinkerpop.gremlin.driver.ser.binary.GraphBinaryReader; +import org.openjdk.jmh.annotations.Benchmark; + +import java.nio.charset.StandardCharsets; +import java.util.UUID; + +public class SerializationBenchmark extends AbstractBenchmarkBase { + + private static final ByteBuf RequestMessageGraphSONBuffer1 = Unpooled.wrappedBuffer( + ("{\"requestId\":{\"@type\":\"g:UUID\",\"@value\":\"9b6d17c0-c5a9-418e-bff6-a25fbb1b175e\"}," + + "\"op\":\"a\",\"processor\":\"b\",\"args\":{}}") + .getBytes(StandardCharsets.UTF_8)); + + private static final ByteBuf RequestMessageGraphSONBuffer2 = Unpooled.wrappedBuffer( + ("{\"requestId\":{\"@type\":\"g:UUID\",\"@value\":\"042b8400-d586-4fcb-b085-2cf2ab2bd5cb\"}," + + "\"op\":\"bytecode\",\"processor\":\"traversal\",\"args\":{\"gremlin\":" + + "{\"@type\":\"g:Bytecode\",\"@value\":{\"step\":[[\"V\"],[\"tail\"]]}},\"aliases\":{\"g\":\"g\"}}}") + .getBytes(StandardCharsets.UTF_8)); + + private static final ByteBuf RequestMessageBinaryBuffer1 = Unpooled.wrappedBuffer(new byte[]{ + // flag + 0x1, + // uuid + (byte) 0xd3, (byte) 0xfd, 0x35, 0x40, 0x67, 0x18, 0x46, (byte) 0x87,(byte) 0x95, 0x6b, (byte) 0xc8, 0x61, + (byte) 0x8a, 0x26, (byte) 0xe3, 0x35, + // string length and string value (a) + 0, 0, 0, 0x01, 0x61, + // string length and string value (b) + 0, 0, 0, 0x01, 0x62, + // Map (no items) + 0, 0, 0, 0 + }); + + private static final ByteBuf RequestMessageBinaryBuffer2 = Unpooled.wrappedBuffer(new byte[]{ + // flag + 0x1, + // uuid + (byte) 0xd3, (byte) 0xfd, 0x35, 0x40, 0x67, 0x18, 0x46, (byte) 0x87,(byte) 0x95, 0x6b, (byte) 0xc8, 0x61, + (byte) 0x8a, 0x26, (byte) 0xe3, 0x35, + // string length and string value (a) + 0, 0, 0, 0x01, 0x61, + // string length and string value (b) + 0, 0, 0, 0x01, 0x62, + // Map (2 items) + 0, 0, 0, 0x2, + // "aliases" + DataType.STRING.getCodeByte(), 0, 0, 0, 0, 0x07, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, + // map { g: g } + DataType.MAP.getCodeByte(), 0, 0, 0, 0, 0x1, + DataType.STRING.getCodeByte(), 0, 0, 0, 0, 0x01, 0x67, + DataType.STRING.getCodeByte(), 0, 0, 0, 0, 0x01, 0x67, + // "gremlin" + DataType.STRING.getCodeByte(), 0, 0, 0, 0, 0x07, 0x67, 0x72, 0x65, 0x6d, 0x6c, 0x69, 0x6e, + // Bytecode for ['V', 'tail'] + DataType.BYTECODE.getCodeByte(), 0, 0, 0, 0, 0x02, + // "V" (no values) + 0, 0, 0, 0x1, 0x56, 0, 0, 0, 0, + // tail (no values) + 0, 0, 0, 0x4, 0x74, 0x61, 0x69, 0x6c, 0, 0, 0, 0, + // no sources + 0, 0, 0, 0 + }); + + private static final UUID id = UUID.randomUUID(); + + private static final GraphBinaryReader binaryReader = new GraphBinaryReader(); + private static final GraphSONMessageSerializerV3d0 graphsonReader = new GraphSONMessageSerializerV3d0(); + + @Benchmark + public RequestMessage testReadMessage1Binary() throws SerializationException { + RequestMessageBinaryBuffer1.readerIndex(0); + return binaryReader.readValue(RequestMessageBinaryBuffer1, RequestMessage.class); + } + + @Benchmark + public RequestMessage testReadMessage2Binary() throws SerializationException { + RequestMessageBinaryBuffer2.readerIndex(0); + return binaryReader.readValue(RequestMessageBinaryBuffer2, RequestMessage.class); + } + + @Benchmark + public RequestMessage testReadMessage1GraphSON() throws SerializationException { + RequestMessageGraphSONBuffer1.readerIndex(0); + return graphsonReader.deserializeRequest(RequestMessageGraphSONBuffer1); + } + + @Benchmark + public RequestMessage testReadMessage2GraphSON() throws SerializationException { + RequestMessageGraphSONBuffer2.readerIndex(0); + return graphsonReader.deserializeRequest(RequestMessageGraphSONBuffer2); + } + + @Benchmark + public RequestMessage testInstanceCreation() { + return RequestMessage.build("a").overrideRequestId(id).processor("b").create(); + } +}