From b98a67211c69d9c97f791e37e5a4ae7a16e327c8 Mon Sep 17 00:00:00 2001 From: leventov Date: Fri, 4 Mar 2016 22:44:26 +0700 Subject: [PATCH] Optimize Integer, Long and Double default serializers --- .../serialization/impl/DoubleDataAccess.java | 120 ++++++++++++++++++ .../serialization/impl/DoubleMarshaller.java | 10 +- .../serialization/impl/IntegerDataAccess.java | 120 ++++++++++++++++++ .../serialization/impl/IntegerMarshaller.java | 10 +- .../serialization/impl/LongDataAccess.java | 120 ++++++++++++++++++ .../serialization/impl/LongMarshaller.java | 10 +- .../impl/SerializationBuilder.java | 6 +- 7 files changed, 381 insertions(+), 15 deletions(-) create mode 100644 src/main/java/net/openhft/chronicle/hash/serialization/impl/DoubleDataAccess.java create mode 100644 src/main/java/net/openhft/chronicle/hash/serialization/impl/IntegerDataAccess.java create mode 100644 src/main/java/net/openhft/chronicle/hash/serialization/impl/LongDataAccess.java diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/DoubleDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/DoubleDataAccess.java new file mode 100644 index 000000000..5da314d4d --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/DoubleDataAccess.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2015 higherfrequencytrading.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package net.openhft.chronicle.hash.serialization.impl; + +import net.openhft.chronicle.algo.hashing.LongHashFunction; +import net.openhft.chronicle.bytes.BytesStore; +import net.openhft.chronicle.bytes.RandomDataInput; +import net.openhft.chronicle.bytes.RandomDataOutput; +import net.openhft.chronicle.hash.AbstractData; +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.serialization.DataAccess; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class DoubleDataAccess extends AbstractData + implements DataAccess, Data { + + // Cache fields + private boolean bsInit; + private transient BytesStore bs; + + /** State field */ + private transient Double instance; + + public DoubleDataAccess() { + initTransients(); + } + + private void initTransients() { + bs = BytesStore.wrap(new byte[8]); + } + + @Override + public RandomDataInput bytes() { + if (!bsInit) { + bsInit = true; + bs.writeDouble(0, instance); + } + return bs; + } + + @Override + public long offset() { + return 0; + } + + @Override + public long size() { + return 8; + } + + @Override + public Double get() { + return instance; + } + + @Override + public Double getUsing(@Nullable Double using) { + return instance; + } + + @Override + public long hash(LongHashFunction f) { + return f.hashLong(Double.doubleToRawLongBits(instance)); + } + + @Override + public boolean equivalent(RandomDataInput source, long sourceOffset) { + return source.readLong(sourceOffset) == Double.doubleToRawLongBits(instance); + } + + @Override + public void writeTo(RandomDataOutput target, long targetOffset) { + target.writeDouble(targetOffset, instance); + } + + @Override + public Data getData(@NotNull Double instance) { + this.instance = instance; + bsInit = false; + return this; + } + + @Override + public void uninit() { + instance = null; + } + + @Override + public void readMarshallable(@NotNull WireIn wireIn) { + // no config fields to read + initTransients(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + // no config fields to write + } + + @Override + public DataAccess copy() { + return new DoubleDataAccess(); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/DoubleMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/DoubleMarshaller.java index b1896b38b..b2b2a45e9 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/DoubleMarshaller.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/DoubleMarshaller.java @@ -17,13 +17,15 @@ package net.openhft.chronicle.hash.serialization.impl; import net.openhft.chronicle.bytes.Bytes; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.chronicle.hash.serialization.BytesWriter; -import net.openhft.chronicle.hash.serialization.SizedReader; -import net.openhft.chronicle.hash.serialization.SizedWriter; +import net.openhft.chronicle.hash.serialization.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +/** + * As a writer for top-level Chronicle Map's key or value type (Long), {@code DoubleMarshaller} is + * deprecated in favor of {@link DoubleDataAccess}. As reader and element writer for {@link + * ListMarshaller} and similar composite marshallers, {@code DoubleMarshaller} is not deprecated. + */ public enum DoubleMarshaller implements SizedReader, BytesReader, SizedWriter, BytesWriter, EnumMarshallable { diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/IntegerDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/IntegerDataAccess.java new file mode 100644 index 000000000..d5fa48c3a --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/IntegerDataAccess.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2015 higherfrequencytrading.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package net.openhft.chronicle.hash.serialization.impl; + +import net.openhft.chronicle.algo.hashing.LongHashFunction; +import net.openhft.chronicle.bytes.BytesStore; +import net.openhft.chronicle.bytes.RandomDataInput; +import net.openhft.chronicle.bytes.RandomDataOutput; +import net.openhft.chronicle.hash.AbstractData; +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.serialization.DataAccess; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class IntegerDataAccess extends AbstractData + implements DataAccess, Data { + + // Cache fields + private boolean bsInit; + private transient BytesStore bs; + + /** State field */ + private transient Integer instance; + + public IntegerDataAccess() { + initTransients(); + } + + private void initTransients() { + bs = BytesStore.wrap(new byte[4]); + } + + @Override + public RandomDataInput bytes() { + if (!bsInit) { + bsInit = true; + bs.writeInt(0, instance); + } + return bs; + } + + @Override + public long offset() { + return 0; + } + + @Override + public long size() { + return 4; + } + + @Override + public Integer get() { + return instance; + } + + @Override + public Integer getUsing(@Nullable Integer using) { + return instance; + } + + @Override + public long hash(LongHashFunction f) { + return f.hashInt(instance); + } + + @Override + public boolean equivalent(RandomDataInput source, long sourceOffset) { + return source.readInt(sourceOffset) == instance; + } + + @Override + public void writeTo(RandomDataOutput target, long targetOffset) { + target.writeInt(targetOffset, instance); + } + + @Override + public Data getData(@NotNull Integer instance) { + this.instance = instance; + return this; + } + + @Override + public void uninit() { + instance = null; + bsInit = false; + } + + @Override + public void readMarshallable(@NotNull WireIn wireIn) { + // no config fields to read + initTransients(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + // no config fields to write + } + + @Override + public DataAccess copy() { + return new IntegerDataAccess(); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/IntegerMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/IntegerMarshaller.java index 5f16081a8..dca93ee9a 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/IntegerMarshaller.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/IntegerMarshaller.java @@ -17,13 +17,15 @@ package net.openhft.chronicle.hash.serialization.impl; import net.openhft.chronicle.bytes.Bytes; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.chronicle.hash.serialization.BytesWriter; -import net.openhft.chronicle.hash.serialization.SizedReader; -import net.openhft.chronicle.hash.serialization.SizedWriter; +import net.openhft.chronicle.hash.serialization.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +/** + * As a writer for top-level Chronicle Map's key or value type (Integer), {@code IntegerMarshaller} + * is deprecated in favor of {@link IntegerDataAccess}. As reader and element writer for {@link + * ListMarshaller} and similar composite marshallers, {@code IntegerMarshaller} is not deprecated. + */ public enum IntegerMarshaller implements SizedReader, BytesReader, SizedWriter, BytesWriter, EnumMarshallable { diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/LongDataAccess.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/LongDataAccess.java new file mode 100644 index 000000000..e384efdf2 --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/LongDataAccess.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2015 higherfrequencytrading.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package net.openhft.chronicle.hash.serialization.impl; + +import net.openhft.chronicle.algo.hashing.LongHashFunction; +import net.openhft.chronicle.bytes.BytesStore; +import net.openhft.chronicle.bytes.RandomDataInput; +import net.openhft.chronicle.bytes.RandomDataOutput; +import net.openhft.chronicle.hash.AbstractData; +import net.openhft.chronicle.hash.Data; +import net.openhft.chronicle.hash.serialization.DataAccess; +import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.WireOut; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public final class LongDataAccess extends AbstractData + implements DataAccess, Data { + + // Cache fields + private boolean bsInit; + private transient BytesStore bs; + + /** State field */ + private transient Long instance; + + public LongDataAccess() { + initTransients(); + } + + private void initTransients() { + bs = BytesStore.wrap(new byte[8]); + } + + @Override + public RandomDataInput bytes() { + if (!bsInit) { + bsInit = true; + bs.writeLong(0, instance); + } + return bs; + } + + @Override + public long offset() { + return 0; + } + + @Override + public long size() { + return 8; + } + + @Override + public Long get() { + return instance; + } + + @Override + public Long getUsing(@Nullable Long using) { + return instance; + } + + @Override + public long hash(LongHashFunction f) { + return f.hashLong(instance); + } + + @Override + public boolean equivalent(RandomDataInput source, long sourceOffset) { + return source.readLong(sourceOffset) == instance; + } + + @Override + public void writeTo(RandomDataOutput target, long targetOffset) { + target.writeLong(targetOffset, instance); + } + + @Override + public Data getData(@NotNull Long instance) { + this.instance = instance; + bsInit = false; + return this; + } + + @Override + public void uninit() { + instance = null; + } + + @Override + public void readMarshallable(@NotNull WireIn wireIn) { + // no config fields to read + initTransients(); + } + + @Override + public void writeMarshallable(@NotNull WireOut wireOut) { + // no config fields to write + } + + @Override + public DataAccess copy() { + return new LongDataAccess(); + } +} diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/LongMarshaller.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/LongMarshaller.java index d38af87b7..b54da39fc 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/LongMarshaller.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/LongMarshaller.java @@ -17,13 +17,15 @@ package net.openhft.chronicle.hash.serialization.impl; import net.openhft.chronicle.bytes.Bytes; -import net.openhft.chronicle.hash.serialization.BytesReader; -import net.openhft.chronicle.hash.serialization.BytesWriter; -import net.openhft.chronicle.hash.serialization.SizedReader; -import net.openhft.chronicle.hash.serialization.SizedWriter; +import net.openhft.chronicle.hash.serialization.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +/** + * As a writer for top-level Chronicle Map's key or value type (Long), {@code LongMarshaller} is + * deprecated in favor of {@link LongDataAccess}. As reader and element writer for {@link + * ListMarshaller} and similar composite marshallers, {@code LongMarshaller} is not deprecated. + */ public enum LongMarshaller implements SizedReader, BytesReader, SizedWriter, BytesWriter, EnumMarshallable { diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/impl/SerializationBuilder.java b/src/main/java/net/openhft/chronicle/hash/serialization/impl/SerializationBuilder.java index f3ba45435..5ada6e67d 100644 --- a/src/main/java/net/openhft/chronicle/hash/serialization/impl/SerializationBuilder.java +++ b/src/main/java/net/openhft/chronicle/hash/serialization/impl/SerializationBuilder.java @@ -95,15 +95,15 @@ public final class SerializationBuilder implements Cloneable { sizeMarshaller(constant(1)); } else if (tClass == Long.class) { reader((SizedReader) LongMarshaller.INSTANCE); - notReusingWriter((SizedWriter) LongMarshaller.INSTANCE); + dataAccess((DataAccess) new LongDataAccess()); sizeMarshaller(constant(8)); } else if (tClass == Double.class) { reader((SizedReader) DoubleMarshaller.INSTANCE); - notReusingWriter((SizedWriter) DoubleMarshaller.INSTANCE); + dataAccess((DataAccess) new DoubleDataAccess()); sizeMarshaller(constant(8)); } else if (tClass == Integer.class) { reader((SizedReader) IntegerMarshaller.INSTANCE); - notReusingWriter((SizedWriter) IntegerMarshaller.INSTANCE); + dataAccess((DataAccess) new IntegerDataAccess()); sizeMarshaller(constant(4)); } else if (tClass == byte[].class) { reader((SizedReader) ByteArraySizedReader.INSTANCE);