From 96c250c6eadc8129e24b6cd3e14a8097765e7ca3 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Thu, 10 Dec 2020 15:55:43 +0100 Subject: [PATCH] [jOOQ/jOOQ#11099] Cache data type attachability in AbstractBinding - It appears that in benchmarks, the instanceof Attachable call (or the method itself, possibly preventing inlining?) in DefaultBinding.AbstractBinding::attach is quite costly. Caching the information for final types brings the 20% speedup in some benchmarks, without regressions --- .../java/org/jooq/impl/DefaultBinding.java | 43 ++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java index 13636b5be4..5d58e69211 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java @@ -124,6 +124,7 @@ import static org.jooq.util.postgres.PostgresUtils.toPGArrayString; import static org.jooq.util.postgres.PostgresUtils.toPGInterval; import java.io.Serializable; +import java.lang.reflect.Modifier; import java.math.BigDecimal; import java.math.BigInteger; import java.sql.Array; @@ -557,22 +558,29 @@ public class DefaultBinding implements Binding { /** * Generated UID */ - private static final long serialVersionUID = -7965247586545864991L; - static final Set NEEDS_PRECISION_SCALE_ON_BIGDECIMAL = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD, HSQLDB); - static final Set REQUIRES_JSON_CAST = SQLDialect.supportedBy(POSTGRES); - static final Set NO_SUPPORT_ENUM_CAST = SQLDialect.supportedBy(POSTGRES); - static final Set NO_SUPPORT_NVARCHAR = SQLDialect.supportedBy(DERBY, FIREBIRD, POSTGRES, SQLITE); + private static final long serialVersionUID = -7965247586545864991L; + static final Set NEEDS_PRECISION_SCALE_ON_BIGDECIMAL = SQLDialect.supportedBy(CUBRID, DERBY, FIREBIRD, HSQLDB); + static final Set REQUIRES_JSON_CAST = SQLDialect.supportedBy(POSTGRES); + static final Set NO_SUPPORT_ENUM_CAST = SQLDialect.supportedBy(POSTGRES); + static final Set NO_SUPPORT_NVARCHAR = SQLDialect.supportedBy(DERBY, FIREBIRD, POSTGRES, SQLITE); - final DataType dataType; - final Converter converter; + final DataType dataType; + final Converter converter; + final boolean attachable; AbstractBinding(DataType dataType, Converter converter) { this.dataType = dataType; this.converter = converter; + + // [#11099] Caching this per binding seems to have a considerable performance effect. + // We must be careful to short circuit instanceof Attachable checks only if we *know* + // the type cannot be attachable, i.e. for final declared types only (such as String) + this.attachable = Attachable.class.isAssignableFrom(converter.toType()) + || !Modifier.isFinal(converter.toType().getModifiers()); } @Override @@ -860,17 +868,32 @@ public class DefaultBinding implements Binding { @Override public final void get(BindingGetResultSetContext ctx) throws SQLException { - ctx.value(attach(converter().from(get0(ctx)), ctx.configuration())); + U value = converter().from(get0(ctx)); + + if (attachable) + value = attach(value, ctx.configuration()); + + ctx.value(value); } @Override public final void get(BindingGetStatementContext ctx) throws SQLException { - ctx.value(attach(converter().from(get0(ctx)), ctx.configuration())); + U value = converter().from(get0(ctx)); + + if (attachable) + value = attach(value, ctx.configuration()); + + ctx.value(value); } @Override public final void get(BindingGetSQLInputContext ctx) throws SQLException { - ctx.value(attach(converter().from(get0(ctx)), ctx.configuration())); + U value = converter().from(get0(ctx)); + + if (attachable) + value = attach(value, ctx.configuration()); + + ctx.value(value); } private static final U attach(U value, Configuration configuration) {