You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by am...@apache.org on 2020/12/25 14:45:52 UTC

[ignite-3] 03/04: Add ASM generated serializer.

This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-13618-asm
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 310ea98821e866ae885790760386b547fd8291df
Author: Andrew Mashenkov <an...@gmail.com>
AuthorDate: Thu Dec 24 22:21:44 2020 +0300

    Add ASM generated serializer.
---
 modules/commons/pom.xml                            |   5 +
 .../schema/marshaller/SerializerFactory.java       |   3 +-
 .../marshaller/asm/AsmSerializerGenerator.java     | 422 +++++++++++++++++++++
 .../IdentityMarshallerCodeGenerator.java}          |  44 +--
 .../marshaller/asm/MarshallerCodeGenerator.java    |  59 +++
 .../asm/ObjectMarshallerCodeGenerator.java         | 165 ++++++++
 .../TupleColumnAccessCodeGenerator.java            |  40 +-
 .../IdentityObjectMarshallerExprGenerator.java     |   2 +-
 .../MarshallerCodeGenerator.java                   |  19 +-
 .../ObjectMarshallerCodeGenerator.java             |   2 +-
 .../SerializerGenerator.java                       |   9 +-
 .../TupleColumnAccessCodeGenerator.java            |   2 +-
 .../benchmarks/SerializerBenchmarkTest.java        |  10 +-
 .../schema/marshaller/JavaSerializerTest.java      |   6 +-
 pom.xml                                            |   1 +
 15 files changed, 718 insertions(+), 71 deletions(-)

diff --git a/modules/commons/pom.xml b/modules/commons/pom.xml
index a5b64e8..d7986fc 100644
--- a/modules/commons/pom.xml
+++ b/modules/commons/pom.xml
@@ -47,6 +47,11 @@
             <artifactId>javapoet</artifactId>
             <version>${javapoet.version}</version>
         </dependency>
+        <dependency>
+            <groupId>com.facebook.presto</groupId>
+            <artifactId>presto-bytecode</artifactId>
+            <version>${prestodb.version}</version>
+        </dependency>
 
         <!-- Test dependencies -->
         <dependency>
diff --git a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/SerializerFactory.java b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/SerializerFactory.java
index cf006c4..77b784c 100644
--- a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/SerializerFactory.java
+++ b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/SerializerFactory.java
@@ -18,10 +18,9 @@
 package org.apache.ignite.internal.schema.marshaller;
 
 import org.apache.ignite.internal.schema.SchemaDescriptor;
-import org.apache.ignite.internal.schema.marshaller.generator.SerializerGenerator;
+import org.apache.ignite.internal.schema.marshaller.codegen.SerializerGenerator;
 import org.apache.ignite.internal.schema.marshaller.reflection.JavaSerializerFactory;
 import org.apache.ignite.lang.IgniteExperimental;
-import org.jetbrains.annotations.ApiStatus;
 
 /**
  * (De)Serializer factory interface.
diff --git a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/AsmSerializerGenerator.java b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/AsmSerializerGenerator.java
new file mode 100644
index 0000000..4c151a9
--- /dev/null
+++ b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/AsmSerializerGenerator.java
@@ -0,0 +1,422 @@
+/*
+ * 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.ignite.internal.schema.marshaller.asm;
+
+import com.facebook.presto.bytecode.Access;
+import com.facebook.presto.bytecode.BytecodeBlock;
+import com.facebook.presto.bytecode.ClassDefinition;
+import com.facebook.presto.bytecode.ClassGenerator;
+import com.facebook.presto.bytecode.MethodDefinition;
+import com.facebook.presto.bytecode.Parameter;
+import com.facebook.presto.bytecode.ParameterizedType;
+import com.facebook.presto.bytecode.Scope;
+import com.facebook.presto.bytecode.Variable;
+import com.facebook.presto.bytecode.control.IfStatement;
+import com.facebook.presto.bytecode.expression.BytecodeExpression;
+import com.facebook.presto.bytecode.expression.BytecodeExpressions;
+import java.io.StringWriter;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.concurrent.TimeUnit;
+import javax.annotation.processing.Generated;
+import jdk.jfr.Experimental;
+import org.apache.ignite.internal.schema.Column;
+import org.apache.ignite.internal.schema.Columns;
+import org.apache.ignite.internal.schema.NativeType;
+import org.apache.ignite.internal.schema.SchemaDescriptor;
+import org.apache.ignite.internal.schema.Tuple;
+import org.apache.ignite.internal.schema.TupleAssembler;
+import org.apache.ignite.internal.schema.marshaller.AbstractSerializer;
+import org.apache.ignite.internal.schema.marshaller.BinaryMode;
+import org.apache.ignite.internal.schema.marshaller.MarshallerUtil;
+import org.apache.ignite.internal.schema.marshaller.SerializationException;
+import org.apache.ignite.internal.schema.marshaller.Serializer;
+import org.apache.ignite.internal.schema.marshaller.SerializerFactory;
+import org.apache.ignite.internal.util.ObjectFactory;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * {@link Serializer} code generator.
+ */
+@Experimental
+public class AsmSerializerGenerator implements SerializerFactory {
+    /** Serializer package name. */
+    public static final String SERIALIZER_PACKAGE_NAME = "org.apache.ignite.internal.schema.marshaller";
+
+    /** Serializer package name prefix. */
+    public static final String SERIALIZER_CLASS_NAME_PREFIX = "SerializerForSchema_";
+
+    /** {@inheritDoc} */
+    @Override public Serializer create(
+        SchemaDescriptor schema,
+        Class<?> keyClass,
+        Class<?> valClass
+    ) {
+        final String className = SERIALIZER_CLASS_NAME_PREFIX + schema.version();
+
+        final StringWriter writer = new StringWriter();
+        try {
+            // Generate Serializer code.
+            long generation = System.nanoTime();
+
+            final ClassDefinition classDef = generateSerializerClass(className, schema, keyClass, valClass);
+
+            long compilationTime = System.nanoTime();
+            generation = compilationTime - generation;
+
+            final Class<? extends Serializer> aClass = ClassGenerator.classGenerator(getClassLoader())
+                .fakeLineNumbers(true)
+                .runAsmVerifier(true)
+                .dumpRawBytecode(true)
+                .dumpClassFilesTo(Paths.get("./target"))
+//                .outputTo(writer)
+                .defineClass(classDef, Serializer.class);
+
+            compilationTime = System.nanoTime() - compilationTime;
+
+            //TODO: pass code to logger on trace level.
+            System.out.println("Serializer created: generated=" + TimeUnit.NANOSECONDS.toMicros(generation) + "us\n" +
+                ", compiled=" + TimeUnit.NANOSECONDS.toMicros(compilationTime) + "us\n" +
+                writer.toString());
+
+            // Instantiate serializer.
+            return aClass.getDeclaredConstructor(SchemaDescriptor.class, Class.class, Class.class)
+                .newInstance(schema, keyClass, valClass);
+
+        }
+        catch (Exception e) {
+            throw new IllegalStateException("Failed to create serializer for key-value pair: schemaVer=" + schema.version() +
+                ", keyClass=" + keyClass.getSimpleName() + ", valueClass=" + valClass.getSimpleName() + " code=\n" + writer.toString(), e);
+        }
+    }
+
+    @NotNull private ClassDefinition generateSerializerClass(String className,
+        SchemaDescriptor schema, Class<?> keyClass, Class<?> valClass) throws ReflectiveOperationException {
+
+        final ClassDefinition classDef = new ClassDefinition(
+            EnumSet.of(Access.PUBLIC),
+            SERIALIZER_PACKAGE_NAME.replace('.', '/') + '/' + className,
+            ParameterizedType.type(AbstractSerializer.class)
+        );
+
+        classDef.declareAnnotation(Generated.class).setValue("value", getClass().getCanonicalName());
+
+        MarshallerCodeGenerator keyMarsh = createMarshaller(keyClass, schema.keyColumns(), 0);
+        MarshallerCodeGenerator valMarsh = createMarshaller(valClass, schema.valueColumns(), schema.keyColumns().length());
+
+        generateStaticHandlers(classDef, keyMarsh, valMarsh);
+
+        generateConstructor(classDef);
+        generateAssemblerFactoryMethod(classDef, schema, keyMarsh, valMarsh);
+
+        generateSerializeMethod(classDef, keyMarsh, valMarsh);
+        generateDeserializeKeyMethod(classDef, keyMarsh);
+        generateDeserializeValueMethod(classDef, valMarsh);
+
+        return classDef;
+    }
+
+    private void generateStaticHandlers(
+        ClassDefinition classDef,
+        MarshallerCodeGenerator keyMarsh,
+        MarshallerCodeGenerator valMarsh
+    ) {
+        keyMarsh.initStaticHandlers(classDef);
+        valMarsh.initStaticHandlers(classDef);
+    }
+
+    @NotNull
+    private static MarshallerCodeGenerator createMarshaller(Class<?> tClass, Columns columns, int firstColumnIdx) {
+        final BinaryMode mode = MarshallerUtil.mode(tClass);
+
+        if (mode == null)
+            return new ObjectMarshallerCodeGenerator(columns, tClass, firstColumnIdx);
+        else
+            return new IdentityMarshallerCodeGenerator(TupleColumnAccessCodeGenerator.createAccessor(mode, firstColumnIdx));
+    }
+
+    private void generateConstructor(ClassDefinition classDef) {
+        final MethodDefinition constrDef = classDef.declareConstructor(
+            EnumSet.of(Access.PUBLIC),
+            Parameter.arg("schema", SchemaDescriptor.class),
+            Parameter.arg("keyClass", Class.class),
+            Parameter.arg("valClass", Class.class)
+        );
+
+        constrDef.getBody()
+            .append(constrDef.getThis())
+            .append(constrDef.getScope().getVariable("schema"))
+            .invokeConstructor(classDef.getSuperClass(), ParameterizedType.type(SchemaDescriptor.class))
+            .ret();
+    }
+
+    private void generateAssemblerFactoryMethod(
+        ClassDefinition classDef,
+        SchemaDescriptor schema,
+        MarshallerCodeGenerator keyMarsh,
+        MarshallerCodeGenerator valMarsh
+    ) throws ReflectiveOperationException {
+        final MethodDefinition methodDef = classDef.declareMethod(
+            EnumSet.of(Access.PROTECTED),
+            "createAssembler",
+            ParameterizedType.type(TupleAssembler.class),
+            Parameter.arg("key", Object.class),
+            Parameter.arg("val", Object.class)
+        );
+        methodDef.declareAnnotation(Override.class);
+
+        final Scope scope = methodDef.getScope();
+        final BytecodeBlock body = methodDef.getBody();
+
+        final Variable varlenKeyCols = scope.declareVariable("varlenKeyCols", body, BytecodeExpressions.defaultValue(int.class));
+        final Variable varlenValueCols = scope.declareVariable("varlenValueCols", body, BytecodeExpressions.defaultValue(int.class));
+        final Variable varlenKeyColsSize = scope.declareVariable("varlenKeyColsSize", body, BytecodeExpressions.defaultValue(int.class));
+        final Variable varlenValueColsSize = scope.declareVariable("varlenValueColsSize", body, BytecodeExpressions.defaultValue(int.class));
+
+        final Variable keyCols = scope.declareVariable(Columns.class, "keyCols");
+        final Variable valCols = scope.declareVariable(Columns.class, "valCols");
+
+        body.append(keyCols.set(
+            methodDef.getThis().getField("schema", SchemaDescriptor.class)
+                .invoke("keyColumns", Columns.class)));
+        body.append(valCols.set(
+            methodDef.getThis().getField("schema", SchemaDescriptor.class)
+                .invoke("valueColumns", Columns.class)));
+
+        Columns columns = schema.keyColumns();
+        if (columns.firstVarlengthColumn() >= 0) {
+            final Variable tmp = scope.createTempVariable(Object.class);
+
+            for (int i = columns.firstVarlengthColumn(); i < columns.length(); i++) {
+                assert !columns.column(i).type().spec().fixedLength();
+
+                body.append(keyMarsh.getValue(classDef.getType(), scope.getVariable("key"), i)).putVariable(tmp);
+                body.append(new IfStatement().condition(BytecodeExpressions.isNotNull(tmp)).ifTrue(
+                    new BytecodeBlock()
+                        .append(varlenKeyCols.increment())
+                        .append(BytecodeExpressions.add(
+                            varlenKeyColsSize,
+                            getColumnValueSize(tmp, keyCols, i))
+                        )
+                        .putVariable(varlenKeyColsSize))
+                );
+            }
+        }
+
+        columns = schema.valueColumns();
+        if (columns.firstVarlengthColumn() >= 0) {
+            final Variable tmp = scope.createTempVariable(Object.class);
+
+            for (int i = columns.firstVarlengthColumn(); i < columns.length(); i++) {
+                assert !columns.column(i).type().spec().fixedLength();
+
+                body.append(valMarsh.getValue(classDef.getType(), scope.getVariable("val"), i)).putVariable(tmp);
+                body.append(new IfStatement().condition(BytecodeExpressions.isNotNull(tmp)).ifTrue(
+                    new BytecodeBlock()
+                        .append(varlenValueCols.increment())
+                        .append(BytecodeExpressions.add(
+                            varlenValueColsSize,
+                            getColumnValueSize(tmp, valCols, i))
+                        )
+                        .putVariable(varlenValueColsSize))
+                );
+            }
+        }
+
+        body.append(BytecodeExpressions.newInstance(TupleAssembler.class,
+            methodDef.getThis().getField("schema", SchemaDescriptor.class),
+            BytecodeExpressions.invokeStatic(TupleAssembler.class, "tupleSize", int.class,
+                keyCols, varlenKeyCols, varlenKeyColsSize,
+                valCols, varlenValueCols, varlenValueColsSize),
+            varlenKeyCols,
+            varlenValueCols));
+
+        body.retObject();
+    }
+
+    @NotNull private BytecodeExpression getColumnValueSize(Variable obj, Variable cols, int i) {
+        return BytecodeExpressions.invokeStatic(MarshallerUtil.class, "getValueSize",
+            int.class,
+            Arrays.asList(Object.class, NativeType.class),
+            obj,
+            cols.invoke("column", Column.class, BytecodeExpressions.constantInt(i))
+                .invoke("type", NativeType.class)
+        );
+    }
+
+    private void generateSerializeMethod(
+        ClassDefinition classDef,
+        MarshallerCodeGenerator keyMarsh,
+        MarshallerCodeGenerator valMarsh
+    ) throws ReflectiveOperationException {
+        final MethodDefinition methodDef = classDef.declareMethod(
+            EnumSet.of(Access.PROTECTED),
+            "serialize0",
+            ParameterizedType.type(byte[].class),
+            Parameter.arg("asm", TupleAssembler.class),
+            Parameter.arg("key", Object.class),
+            Parameter.arg("val", Object.class)
+        )
+            .addException(SerializationException.class);
+        methodDef.declareAnnotation(Override.class);
+
+        final Variable asm = methodDef.getScope().getVariable("asm");
+
+        methodDef.getBody()
+            .append(new IfStatement().condition(BytecodeExpressions.isNull(asm)).ifTrue(
+                new BytecodeBlock()
+                    .append(BytecodeExpressions.newInstance(IllegalStateException.class, BytecodeExpressions.constantString("ASM can't be null.")))
+                    .throwObject()
+            ));
+
+        methodDef.getBody()
+            .append(
+                keyMarsh.marshallObject(
+                    classDef.getType(),
+                    asm,
+                    methodDef.getScope().getVariable("key"))
+            )
+            .append(
+                valMarsh.marshallObject(
+                    classDef.getType(),
+                    asm,
+                    methodDef.getScope().getVariable("val"))
+            )
+            .append(asm.invoke("build", byte[].class))
+            .retObject();
+    }
+
+    private void generateDeserializeKeyMethod(ClassDefinition classDef,
+        MarshallerCodeGenerator keyMarsh) throws ReflectiveOperationException {
+        final MethodDefinition methodDef = classDef.declareMethod(
+            EnumSet.of(Access.PROTECTED),
+            "deserializeKey0",
+            ParameterizedType.type(Object.class),
+            Parameter.arg("tuple", Tuple.class)
+        )
+            .addException(SerializationException.class);
+        methodDef.declareAnnotation(Override.class);
+
+        final Variable obj = methodDef.getScope().declareVariable(Object.class, "obj");
+
+        methodDef.getBody()
+            .append(keyMarsh.unmarshallObject(classDef.getType(), methodDef.getScope().getVariable("tuple"), obj))
+            .append(obj)
+            .retObject();
+    }
+
+    private void generateDeserializeValueMethod(ClassDefinition classDef,
+        MarshallerCodeGenerator valMarsh) throws ReflectiveOperationException {
+        final MethodDefinition methodDef = classDef.declareMethod(
+            EnumSet.of(Access.PROTECTED),
+            "deserializeValue0",
+            ParameterizedType.type(Object.class),
+            Parameter.arg("tuple", Tuple.class)
+        )
+            .addException(SerializationException.class);
+        methodDef.declareAnnotation(Override.class);
+
+        final Variable obj = methodDef.getScope().declareVariable(Object.class, "obj");
+
+        methodDef.getBody()
+            .append(valMarsh.unmarshallObject(classDef.getType(), methodDef.getScope().getVariable("tuple"), obj))
+            .append(obj)
+            .retObject();
+    }
+
+//    /**
+//     * @param valMarsh Value marshaller code generator.
+//     * @return Deserialize value method spec.
+//     */
+//    private MethodSpec generateDeserializeValueMethod(MarshallerCodeGenerator valMarsh) {
+//        return MethodSpec
+//            .methodBuilder("deserializeValue0")
+//            .addAnnotation(Override.class)
+//            .addModifiers(Modifier.PROTECTED, Modifier.FINAL)
+//            .addParameter(Tuple.class, "tuple", Modifier.FINAL)
+//            .addException(SerializationException.class)
+//            .returns(TypeName.OBJECT)
+//
+//            .beginControlFlow("try")
+//            .addCode(valMarsh.unmarshallObjectCode("tuple"))
+//            .nextControlFlow("catch($T th)", Throwable.class)
+//            .addStatement("throw new $T(th)", SerializationException.class)
+//            .endControlFlow()
+//            .build();
+//    }
+//
+//    /**
+//     * @param keyMarsh Key marshaller code generator.
+//     * @return Deserialize key method spec.
+//     */
+//    private MethodSpec generateDeserializeKeyMethod(MarshallerCodeGenerator keyMarsh) {
+//        return MethodSpec
+//            .methodBuilder("deserializeKey0")
+//            .addAnnotation(Override.class)
+//            .addModifiers(Modifier.PROTECTED, Modifier.FINAL)
+//            .addParameter(Tuple.class, "tuple", Modifier.FINAL)
+//            .addException(SerializationException.class)
+//            .returns(TypeName.OBJECT)
+//
+//            .beginControlFlow("try")
+//            .addCode(keyMarsh.unmarshallObjectCode("tuple"))
+//            .nextControlFlow("catch($T th)", Throwable.class)
+//            .addStatement("throw new $T(th)", SerializationException.class)
+//            .endControlFlow()
+//            .build();
+//    }
+//
+//    /**
+//     * Creates marshaller code generator for given class.
+//     *
+//     * @param tClass Target class.
+//     * @param factoryRefVar Object factory variable.
+//     * @param columns Columns that tClass mapped to.
+//     * @param firstColIdx First column absolute index in schema.
+//     * @return Marshaller code generator.
+//     */
+//    private MarshallerCodeGenerator createObjectMarshaller(
+//        Class<?> tClass,
+//        @Nullable String factoryRefVar,
+//        Columns columns,
+//        int firstColIdx
+//    ) {
+//        BinaryMode mode = MarshallerUtil.mode(tClass);
+//
+//        if (mode != null) // Simple type.
+//            return new IdentityObjectMarshallerExprGenerator(TupleColumnAccessCodeGenerator.createAccessor(mode, firstColIdx));
+//        else
+//            return new ObjectMarshallerCodeGenerator(tClass, factoryRefVar, columns, firstColIdx);
+//    }
+
+    private static BytecodeExpression cretaObjectFactoryExpr(MethodDefinition constrDef, String aClass) {
+        return BytecodeExpressions.invokeStatic(
+            MarshallerUtil.class,
+            "factoryForClass",
+            ObjectFactory.class,
+            constrDef.getScope().getVariable(aClass)
+        );
+    }
+
+    private static ClassLoader getClassLoader() {
+        return Thread.currentThread().getContextClassLoader() == null ?
+            ClassLoader.getSystemClassLoader() :
+            Thread.currentThread().getContextClassLoader();
+    }
+}
diff --git a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/IdentityObjectMarshallerExprGenerator.java b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/IdentityMarshallerCodeGenerator.java
similarity index 51%
copy from modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/IdentityObjectMarshallerExprGenerator.java
copy to modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/IdentityMarshallerCodeGenerator.java
index 5778a5a..ddf0d24 100644
--- a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/IdentityObjectMarshallerExprGenerator.java
+++ b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/IdentityMarshallerCodeGenerator.java
@@ -15,17 +15,19 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema.marshaller.generator;
+package org.apache.ignite.internal.schema.marshaller.asm;
 
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.TypeSpec;
+import com.facebook.presto.bytecode.BytecodeNode;
+import com.facebook.presto.bytecode.ParameterizedType;
+import com.facebook.presto.bytecode.Variable;
+import com.facebook.presto.bytecode.expression.BytecodeExpressions;
 import org.apache.ignite.internal.schema.marshaller.Serializer;
 
 /**
  * Generate {@link Serializer} method's bodies for simple types.
  */
-class IdentityObjectMarshallerExprGenerator implements MarshallerCodeGenerator {
-    /** Tuple column accessor. */
+class IdentityMarshallerCodeGenerator implements MarshallerCodeGenerator {
+    /** Object field access expression generator. */
     private final TupleColumnAccessCodeGenerator columnAccessor;
 
     /**
@@ -33,34 +35,28 @@ class IdentityObjectMarshallerExprGenerator implements MarshallerCodeGenerator {
      *
      * @param columnAccessor Tuple column code generator.
      */
-    IdentityObjectMarshallerExprGenerator(TupleColumnAccessCodeGenerator columnAccessor) {
+    public IdentityMarshallerCodeGenerator(TupleColumnAccessCodeGenerator columnAccessor) {
         this.columnAccessor = columnAccessor;
     }
 
     /** {@inheritDoc} */
-    @Override public boolean isSimpleType() {
-        return true;
+    @Override public BytecodeNode getValue(ParameterizedType type, Variable key, int i) {
+        return key;
     }
 
     /** {@inheritDoc} */
-    @Override public CodeBlock unmarshallObjectCode(String tupleExpr) {
-        return CodeBlock.builder()
-            .addStatement("return $L", columnAccessor.read(tupleExpr))
-            .build();
+    @Override public BytecodeNode marshallObject(ParameterizedType serializerClass, Variable asm, Variable obj) {
+        return asm.invoke(columnAccessor.writeMethodName(), void.class, obj.cast(columnAccessor.writeArgType()));
     }
 
     /** {@inheritDoc} */
-    @Override public CodeBlock marshallObjectCode(String asm, String objVar) {
-        return columnAccessor.write(asm, objVar);
-    }
-
-    /** {@inheritDoc} */
-    @Override public CodeBlock getValueCode(String objVar, int colIdx) {
-        return CodeBlock.of(objVar);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void initStaticHandlers(TypeSpec.Builder builder, CodeBlock.Builder staticBuilder) {
-        throw new UnsupportedOperationException("Static handlers are not applicable to simple types.");
+    @Override public BytecodeNode unmarshallObject(ParameterizedType type, Variable tuple, Variable obj) {
+        return obj.set(
+            tuple.invoke(
+                columnAccessor.readMethodName(),
+                columnAccessor.mappedType(),
+                BytecodeExpressions.constantInt(columnAccessor.columnIdx())
+            )
+        );
     }
 }
diff --git a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/MarshallerCodeGenerator.java b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/MarshallerCodeGenerator.java
new file mode 100644
index 0000000..6442bc4
--- /dev/null
+++ b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/MarshallerCodeGenerator.java
@@ -0,0 +1,59 @@
+/*
+ * 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.ignite.internal.schema.marshaller.asm;
+
+import com.facebook.presto.bytecode.BytecodeNode;
+import com.facebook.presto.bytecode.ClassDefinition;
+import com.facebook.presto.bytecode.ParameterizedType;
+import com.facebook.presto.bytecode.Variable;
+
+/**
+ * Marshaller code generator.
+ */
+public interface MarshallerCodeGenerator {
+    /**
+     * @param serializerClass Serializer type.
+     * @param obj Target object variable.
+     * @param colIdx Column index.
+     * @return Object field value for given column.
+     */
+    BytecodeNode getValue(ParameterizedType serializerClass, Variable obj, int colIdx);
+
+    /**
+     * @param serializerClass Serializer type
+     * @param asm Tuple assempler.
+     * @param obj Target object variable.
+     * @return Unmarshall object code.
+     */
+    BytecodeNode marshallObject(ParameterizedType serializerClass, Variable asm, Variable obj);
+
+    /**
+     * @param serializerClass Serializer type
+     * @param tuple Tuple.
+     * @param obj Result object variable.
+     * @return Unmarshall object code.
+     */
+    BytecodeNode unmarshallObject(ParameterizedType serializerClass, Variable tuple, Variable obj);
+
+    /**
+     * @param classDef Class definition.
+     */
+    default void initStaticHandlers(ClassDefinition classDef) {
+
+    }
+}
diff --git a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/ObjectMarshallerCodeGenerator.java b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/ObjectMarshallerCodeGenerator.java
new file mode 100644
index 0000000..cda6bb6
--- /dev/null
+++ b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/ObjectMarshallerCodeGenerator.java
@@ -0,0 +1,165 @@
+/*
+ * 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.ignite.internal.schema.marshaller.asm;
+
+import com.facebook.presto.bytecode.Access;
+import com.facebook.presto.bytecode.BytecodeBlock;
+import com.facebook.presto.bytecode.BytecodeNode;
+import com.facebook.presto.bytecode.ClassDefinition;
+import com.facebook.presto.bytecode.FieldDefinition;
+import com.facebook.presto.bytecode.MethodDefinition;
+import com.facebook.presto.bytecode.ParameterizedType;
+import com.facebook.presto.bytecode.Variable;
+import com.facebook.presto.bytecode.control.IfStatement;
+import com.facebook.presto.bytecode.expression.BytecodeExpression;
+import com.facebook.presto.bytecode.expression.BytecodeExpressions;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.EnumSet;
+import org.apache.ignite.internal.schema.Columns;
+import org.apache.ignite.internal.schema.marshaller.MarshallerUtil;
+import org.apache.ignite.internal.schema.marshaller.Serializer;
+
+/**
+ * Generates {@link Serializer} methods code.
+ */
+class ObjectMarshallerCodeGenerator implements MarshallerCodeGenerator {
+    /** Target class. */
+    private final Class<?> tClass;
+
+    /** Mapped columns. */
+    private final Columns columns;
+
+    /** Object field access expression generators. */
+    private final TupleColumnAccessCodeGenerator[] columnAccessors;
+
+    public ObjectMarshallerCodeGenerator(Columns columns, Class<?> tClass, int firstColIdx) {
+        this.columns = columns;
+        this.tClass = tClass;
+        columnAccessors = new TupleColumnAccessCodeGenerator[columns.length()];
+
+        try {
+            for (int i = 0; i < columns.length(); i++) {
+                final Field field = tClass.getDeclaredField(columns.column(i).name());
+
+                columnAccessors[i] = TupleColumnAccessCodeGenerator.createAccessor(MarshallerUtil.mode(field.getType()), i + firstColIdx);
+            }
+        }
+        catch (NoSuchFieldException ex) {
+            throw new IllegalStateException(ex);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public BytecodeNode getValue(ParameterizedType serializerClass, Variable obj,
+        int i) {
+        final TupleColumnAccessCodeGenerator columnAccessor = columnAccessors[i];
+
+        return BytecodeExpressions.getStatic(serializerClass, "FIELD_HANDER_" + columnAccessor.columnIdx(), ParameterizedType.type(VarHandle.class))
+            .invoke("get", columnAccessor.mappedType(), obj.cast(tClass));
+    }
+
+    /** {@inheritDoc} */
+    @Override public BytecodeBlock marshallObject(ParameterizedType serializerClass, Variable asm, Variable obj) {
+        final BytecodeBlock block = new BytecodeBlock();
+        final BytecodeExpression obj0 = obj.cast(tClass);
+
+        for (int i = 0; i < columns.length(); i++) {
+            final TupleColumnAccessCodeGenerator columnAccessor = columnAccessors[i];
+
+            final BytecodeExpression fld = BytecodeExpressions.getStatic(serializerClass, "FIELD_HANDER_" + columnAccessor.columnIdx(), ParameterizedType.type(VarHandle.class))
+                .invoke("get", columnAccessor.mappedType(), obj0);
+
+            final BytecodeExpression marshallNonNulExpr = asm.invoke(
+                columnAccessor.writeMethodName(),
+                void.class,
+                Arrays.asList(columnAccessor.writeArgType()),
+                fld.cast(columnAccessor.writeArgType()));
+
+            if (columns.column(i).nullable())
+                block.append(new BytecodeBlock().append(
+                    new IfStatement().condition(BytecodeExpressions.isNull(fld))
+                        .ifTrue(asm.invoke("appendNull", void.class))
+                        .ifFalse(marshallNonNulExpr))
+                );
+            else
+                block.append(marshallNonNulExpr);
+        }
+
+        return block;
+    }
+
+    /** {@inheritDoc} */
+    @Override public BytecodeBlock unmarshallObject(ParameterizedType serializerClass, Variable tuple, Variable obj) {
+        final BytecodeBlock block = new BytecodeBlock();
+        final BytecodeExpression obj0 = obj.cast(tClass);
+
+        block.append(obj.set(BytecodeExpressions.newInstance(tClass)));
+
+        for (int i = 0; i < columns.length(); i++) {
+            final TupleColumnAccessCodeGenerator columnAccessor = columnAccessors[i];
+
+            final BytecodeExpression val = tuple.invoke(
+                columnAccessor.readMethodName(),
+                columnAccessor.mappedType(),
+                BytecodeExpressions.constantInt(columnAccessor.columnIdx())
+            );
+
+            block.append(BytecodeExpressions.getStatic(serializerClass, "FIELD_HANDER_" + columnAccessor.columnIdx(), ParameterizedType.type(VarHandle.class))
+                .invoke("set", void.class, obj0, val)
+            );
+        }
+
+        return block;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void initStaticHandlers(ClassDefinition classDef) {
+        final MethodDefinition init = classDef.getClassInitializer();
+
+        final BytecodeBlock body = init.getBody();
+        final Variable lookup = init.getScope().createTempVariable(MethodHandles.Lookup.class);
+
+        body.append(
+            lookup.set(
+                BytecodeExpressions.invokeStatic(
+                    MethodHandles.class,
+                    "privateLookupIn",
+                    MethodHandles.Lookup.class,
+                    BytecodeExpressions.constantClass(tClass),
+                    BytecodeExpressions.invokeStatic(MethodHandles.class, "lookup", MethodHandles.Lookup.class))
+            ));
+
+        for (int i = 0; i < columnAccessors.length; i++) {
+            final FieldDefinition fld = classDef.declareField(EnumSet.of(Access.PRIVATE, Access.STATIC, Access.FINAL),
+                "FIELD_HANDER_" + columnAccessors[i].columnIdx(), VarHandle.class);
+
+            body.append(
+                BytecodeExpressions.setStatic(fld, lookup.invoke(
+                    "findVarHandle",
+                    VarHandle.class,
+                    BytecodeExpressions.constantClass(tClass),
+                    BytecodeExpressions.constantString(columns.column(i).name()),
+                    BytecodeExpressions.constantClass(columnAccessors[i].mappedType())
+                ))
+            );
+        }
+    }
+}
diff --git a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/TupleColumnAccessCodeGenerator.java b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/TupleColumnAccessCodeGenerator.java
similarity index 79%
copy from modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/TupleColumnAccessCodeGenerator.java
copy to modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/TupleColumnAccessCodeGenerator.java
index 51186de..c4a715a 100644
--- a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/TupleColumnAccessCodeGenerator.java
+++ b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/asm/TupleColumnAccessCodeGenerator.java
@@ -15,9 +15,8 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema.marshaller.generator;
+package org.apache.ignite.internal.schema.marshaller.asm;
 
-import com.squareup.javapoet.CodeBlock;
 import java.util.BitSet;
 import java.util.UUID;
 import org.apache.ignite.internal.schema.marshaller.BinaryMode;
@@ -31,7 +30,7 @@ public class TupleColumnAccessCodeGenerator {
      * @param colIdx Column index in schema.
      * @return Tuple column access code generator.
      */
-    static TupleColumnAccessCodeGenerator createAccessor(BinaryMode mode, int colIdx) {
+    public static TupleColumnAccessCodeGenerator createAccessor(BinaryMode mode, int colIdx) {
         switch (mode) {
             case P_BYTE:
                 return new TupleColumnAccessCodeGenerator("byteValue", "appendByte", byte.class, colIdx);
@@ -122,35 +121,16 @@ public class TupleColumnAccessCodeGenerator {
         return colIdx;
     }
 
-    /**
-     * @param tuple Tuple.
-     * @return Code that reads column value from tuple.
-     */
-    public CodeBlock read(String tuple) {
-        return CodeBlock.of("($T)$L.$L($L)", mappedType, tuple, readMethodName, colIdx);
+    public String readMethodName() {
+        return readMethodName;
     }
 
-    /**
-     * @param asmVar Tuple assembler var.
-     * @param valExpr Value expression.
-     * @return Code that writes value to tuple column.
-     */
-    public CodeBlock write(String asmVar, String valExpr) {
-        if (mappedType.isPrimitive())
-            return CodeBlock.builder().addStatement("$L.$L(($T)$L)", asmVar, writeMethodName, writeArgType, valExpr).build();
-        else {
-            return CodeBlock.builder()
-                .add("{\n").indent()
-                .addStatement("Object fVal")
-                .beginControlFlow("if((fVal = $L) == null)", valExpr)
-                .addStatement("$L.appendNull()", asmVar)
-                .nextControlFlow("else")
-                .addStatement("$L.$L(($T)fVal)", asmVar, writeMethodName, writeArgType)
-                .endControlFlow()
-                .unindent()
-                .add("}\n")
-                .build();
-        }
+    public String writeMethodName() {
+        return writeMethodName;
+    }
+
+    public Class<?> writeArgType() {
+        return writeArgType;
     }
 
     public Class<?> mappedType() {
diff --git a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/IdentityObjectMarshallerExprGenerator.java b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/codegen/IdentityObjectMarshallerExprGenerator.java
similarity index 97%
rename from modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/IdentityObjectMarshallerExprGenerator.java
rename to modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/codegen/IdentityObjectMarshallerExprGenerator.java
index 5778a5a..77151d9 100644
--- a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/IdentityObjectMarshallerExprGenerator.java
+++ b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/codegen/IdentityObjectMarshallerExprGenerator.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema.marshaller.generator;
+package org.apache.ignite.internal.schema.marshaller.codegen;
 
 import com.squareup.javapoet.CodeBlock;
 import com.squareup.javapoet.TypeSpec;
diff --git a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/MarshallerCodeGenerator.java b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/codegen/MarshallerCodeGenerator.java
similarity index 57%
rename from modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/MarshallerCodeGenerator.java
rename to modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/codegen/MarshallerCodeGenerator.java
index bca3256..062d773 100644
--- a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/MarshallerCodeGenerator.java
+++ b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/codegen/MarshallerCodeGenerator.java
@@ -1,4 +1,21 @@
-package org.apache.ignite.internal.schema.marshaller.generator;
+/*
+ * 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.ignite.internal.schema.marshaller.codegen;
 
 import com.squareup.javapoet.CodeBlock;
 import com.squareup.javapoet.TypeSpec;
diff --git a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/ObjectMarshallerCodeGenerator.java b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/codegen/ObjectMarshallerCodeGenerator.java
similarity index 98%
rename from modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/ObjectMarshallerCodeGenerator.java
rename to modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/codegen/ObjectMarshallerCodeGenerator.java
index d1fa6d1..49a123d 100644
--- a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/ObjectMarshallerCodeGenerator.java
+++ b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/codegen/ObjectMarshallerCodeGenerator.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema.marshaller.generator;
+package org.apache.ignite.internal.schema.marshaller.codegen;
 
 import com.squareup.javapoet.CodeBlock;
 import com.squareup.javapoet.FieldSpec;
diff --git a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/SerializerGenerator.java b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/codegen/SerializerGenerator.java
similarity index 98%
rename from modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/SerializerGenerator.java
rename to modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/codegen/SerializerGenerator.java
index 5621cbb..65352f1 100644
--- a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/SerializerGenerator.java
+++ b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/codegen/SerializerGenerator.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema.marshaller.generator;
+package org.apache.ignite.internal.schema.marshaller.codegen;
 
 import com.squareup.javapoet.AnnotationSpec;
 import com.squareup.javapoet.ArrayTypeName;
@@ -28,7 +28,6 @@ import com.squareup.javapoet.TypeSpec;
 import java.lang.invoke.MethodHandles;
 import java.lang.reflect.InvocationTargetException;
 import java.util.Objects;
-import java.util.concurrent.TimeUnit;
 import javax.annotation.processing.Generated;
 import javax.lang.model.element.Modifier;
 import jdk.jfr.Experimental;
@@ -71,8 +70,8 @@ public class SerializerGenerator implements SerializerFactory {
             generation = System.nanoTime() - generation;
 
             //TODO: pass code to logger on trace level.
-            System.out.println("Serializer code generated in " + TimeUnit.NANOSECONDS.toMicros(generation) + "us");
-                        System.out.println(javaFile.toString());
+//            System.out.println("Serializer code generated in " + TimeUnit.NANOSECONDS.toMicros(generation) + "us");
+//                        System.out.println(javaFile.toString());
 
             // Compile.
             long compilation = System.nanoTime();
@@ -87,7 +86,7 @@ public class SerializerGenerator implements SerializerFactory {
                 .newInstance(schema, keyClass, valClass);
 
         }
-        catch (InstantiationException | ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+        catch (InstantiationException | ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e){
             throw new IllegalStateException("Failed to create serializer for key-value pair: schemaVer=" + schema.version() +
                 ", keyClass=" + keyClass.getSimpleName() + ", valueClass=" + valClass.getSimpleName(), e);
         }
diff --git a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/TupleColumnAccessCodeGenerator.java b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/codegen/TupleColumnAccessCodeGenerator.java
similarity index 99%
rename from modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/TupleColumnAccessCodeGenerator.java
rename to modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/codegen/TupleColumnAccessCodeGenerator.java
index 51186de..3d7607f 100644
--- a/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/generator/TupleColumnAccessCodeGenerator.java
+++ b/modules/commons/src/main/java/org/apache/ignite/internal/schema/marshaller/codegen/TupleColumnAccessCodeGenerator.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.schema.marshaller.generator;
+package org.apache.ignite.internal.schema.marshaller.codegen;
 
 import com.squareup.javapoet.CodeBlock;
 import java.util.BitSet;
diff --git a/modules/commons/src/test/java/org/apache/ignite/internal/benchmarks/SerializerBenchmarkTest.java b/modules/commons/src/test/java/org/apache/ignite/internal/benchmarks/SerializerBenchmarkTest.java
index d92825a..cd56f99 100644
--- a/modules/commons/src/test/java/org/apache/ignite/internal/benchmarks/SerializerBenchmarkTest.java
+++ b/modules/commons/src/test/java/org/apache/ignite/internal/benchmarks/SerializerBenchmarkTest.java
@@ -30,6 +30,7 @@ import org.apache.ignite.internal.schema.SchemaDescriptor;
 import org.apache.ignite.internal.schema.marshaller.CompilerUtils;
 import org.apache.ignite.internal.schema.marshaller.Serializer;
 import org.apache.ignite.internal.schema.marshaller.SerializerFactory;
+import org.apache.ignite.internal.schema.marshaller.asm.AsmSerializerGenerator;
 import org.apache.ignite.internal.util.Factory;
 import org.apache.ignite.internal.util.ObjectFactory;
 import org.openjdk.jmh.annotations.Benchmark;
@@ -71,11 +72,11 @@ public class SerializerBenchmarkTest {
     private Factory<?> objectFactory;
 
     /** Object fields count. */
-    @Param({/*"0", "1", */"10", "100"})
+    @Param({"0", "1", "10", "100"})
     public int fieldsCount;
 
     /** Serializer. */
-    @Param({"Generated", "Java"})
+    @Param({"Generated", "ASM", "Java"})
     public String serializerName;
 
     /**
@@ -93,7 +94,7 @@ public class SerializerBenchmarkTest {
      * @throws Exception If failed.
      */
     @Setup
-    public void init() throws Exception {
+    public void init() {
         Thread.currentThread().setContextClassLoader(CompilerUtils.dynamicClassLoader());
 
         long seed = System.currentTimeMillis();
@@ -117,6 +118,8 @@ public class SerializerBenchmarkTest {
 
         if ("Java".equals(serializerName))
             serializer = SerializerFactory.createJavaSerializerFactory().create(schema, Long.class, valClass);
+        else if ("ASM".equals(serializerName))
+            serializer = new AsmSerializerGenerator().create(schema, Long.class, valClass);
         else
             serializer = SerializerFactory.createGeneratedSerializerFactory().create(schema, Long.class, valClass);
     }
@@ -169,7 +172,6 @@ public class SerializerBenchmarkTest {
      * @param maxFields Max class member fields.
      * @param fieldType Field type.
      * @return Generated test object class.
-     * @throws Exception If failed.
      */
     private Class<?> createGeneratedObjectClass(int maxFields, Class<?> fieldType) {
         final String packageName = "org.apache.ignite.internal.benchmarks";
diff --git a/modules/commons/src/test/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerTest.java b/modules/commons/src/test/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerTest.java
index 7b41412..4db6027 100644
--- a/modules/commons/src/test/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerTest.java
+++ b/modules/commons/src/test/java/org/apache/ignite/internal/schema/marshaller/JavaSerializerTest.java
@@ -35,7 +35,8 @@ import org.apache.ignite.internal.schema.NativeType;
 import org.apache.ignite.internal.schema.NativeTypeSpec;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
 import org.apache.ignite.internal.schema.TestUtils;
-import org.apache.ignite.internal.schema.marshaller.generator.SerializerGenerator;
+import org.apache.ignite.internal.schema.marshaller.asm.AsmSerializerGenerator;
+import org.apache.ignite.internal.schema.marshaller.codegen.SerializerGenerator;
 import org.apache.ignite.internal.schema.marshaller.reflection.JavaSerializerFactory;
 import org.apache.ignite.internal.util.ObjectFactory;
 import org.junit.jupiter.api.BeforeEach;
@@ -69,8 +70,9 @@ public class JavaSerializerTest {
      */
     private static List<SerializerFactory> serializerFactoryProvider() {
         return Arrays.asList(
+            new JavaSerializerFactory(),
             new SerializerGenerator(),
-            new JavaSerializerFactory()
+            new AsmSerializerGenerator()
         );
     }
 
diff --git a/pom.xml b/pom.xml
index 26ab8c3..5f152c7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -50,6 +50,7 @@
 
         <!-- Dependencies versions. -->
         <javapoet.version>1.13.0</javapoet.version>
+        <prestodb.version>0.245</prestodb.version>
         <javax.annotation.api.version>1.3.2</javax.annotation.api.version>
         <jetbrains.annotations.version>20.1.0</jetbrains.annotations.version>
         <jmh.framework.verion>1.9.3</jmh.framework.verion>