From 9b0bfc631df241d55e97a2a819d55cb553e3a4b7 Mon Sep 17 00:00:00 2001 From: leventov Date: Fri, 31 Jul 2015 01:50:27 +0300 Subject: [PATCH] Removed ChronicleHashBuilderImpl and ChronicleMapBuilder minor cleanup --- .../chronicle/hash/ChronicleHashBuilder.java | 10 +- .../hash/impl/ChronicleHashBuilderImpl.java | 43 ------ .../hash/impl/VanillaChronicleHash.java | 6 +- .../chronicle/map/ChronicleMapBuilder.java | 144 +++++++++++------- 4 files changed, 104 insertions(+), 99 deletions(-) delete mode 100644 src/main/java/net/openhft/chronicle/hash/impl/ChronicleHashBuilderImpl.java diff --git a/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilder.java b/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilder.java index 6bc3f881f..c52501226 100755 --- a/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilder.java +++ b/src/main/java/net/openhft/chronicle/hash/ChronicleHashBuilder.java @@ -100,6 +100,9 @@ public interface ChronicleHashBuilder, *

If key is a boxed primitive type or {@link Byteable} subclass, i. e. if key size is known * statically, it is automatically accounted and shouldn't be specified by user. * + *

Calling this method clears any previous {@link #constantKeySizeBySample(Object)} and + * {@link #averageKey(Object)} configurations. + * * @param averageKeySize the average number of bytes, taken by serialized form of keys * @return this builder back * @throws IllegalStateException if key size is known statically and shouldn't be configured @@ -129,8 +132,8 @@ public interface ChronicleHashBuilder, *

If key is a boxed primitive type or {@link Byteable} subclass, i. e. if key size is known * statically, it is automatically accounted and shouldn't be specified by user. * - *

Calling this method clears any previous {@link #constantKeySizeBySample(Object)} - * configuration. + *

Calling this method clears any previous {@link #constantKeySizeBySample(Object)} and + * {@link #averageKeySize(double)} configurations. * * @param averageKey the average (by footprint in serialized form) key, is going to be put * into the hash containers, created by this builder @@ -153,7 +156,8 @@ public interface ChronicleHashBuilder, *

If key size varies, method {@link #averageKeySize(double)} should be called instead of * this one. * - *

Calling this method clears any previous {@link #averageKey(Object)} configuration. + *

Calling this method clears any previous {@link #averageKey(Object)} and + * {@link #averageKeySize(double)} configurations. * * @param sampleKey the sample key * @return this builder back diff --git a/src/main/java/net/openhft/chronicle/hash/impl/ChronicleHashBuilderImpl.java b/src/main/java/net/openhft/chronicle/hash/impl/ChronicleHashBuilderImpl.java deleted file mode 100644 index c5a51ddaa..000000000 --- a/src/main/java/net/openhft/chronicle/hash/impl/ChronicleHashBuilderImpl.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.impl; - - -import net.openhft.chronicle.hash.ChronicleHash; -import net.openhft.chronicle.hash.ChronicleHashBuilder; -import net.openhft.chronicle.hash.serialization.internal.SerializationBuilder; - -//TODO remove this temporary interface -public interface ChronicleHashBuilderImpl, - B extends ChronicleHashBuilder> extends ChronicleHashBuilder { - - SerializationBuilder keyBuilder(); - - int actualSegments(boolean replicated); - - long entriesPerSegment(boolean replicated); - - long chunkSize(boolean replicated); - - int segmentHeaderSize(boolean replicated); - - long actualChunksPerSegment(boolean replicated); - - int maxChunksPerEntry(); - - int segmentEntrySpaceInnerOffset(boolean replicated); -} diff --git a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java index 10e20f132..f1aaa1692 100644 --- a/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java +++ b/src/main/java/net/openhft/chronicle/hash/impl/VanillaChronicleHash.java @@ -27,6 +27,7 @@ import net.openhft.chronicle.hash.serialization.SizeMarshaller; import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop; import net.openhft.chronicle.hash.serialization.internal.MetaProvider; import net.openhft.chronicle.hash.serialization.internal.SerializationBuilder; +import net.openhft.chronicle.map.ChronicleMapBuilder; import net.openhft.lang.io.Bytes; import net.openhft.lang.io.BytesStore; import net.openhft.lang.io.MappedStore; @@ -107,7 +108,8 @@ public abstract class VanillaChronicleHash builder, boolean replicated) { + @SuppressWarnings("deprecation") + public VanillaChronicleHash(ChronicleMapBuilder builder, boolean replicated) { // Version dataFileVersion = BuildVersion.version(); @@ -126,7 +128,7 @@ public abstract class VanillaChronicleHash implements - ChronicleHashBuilderImpl, ChronicleMapBuilder>, + ChronicleHashBuilder, ChronicleMapBuilder>, MapBuilder>, Serializable { static final byte UDP_REPLICATION_MODIFICATION_ITERATOR_ID = (byte) 127; @@ -132,8 +132,6 @@ public final class ChronicleMapBuilder implements SerializationBuilder keyBuilder; SerializationBuilder valueBuilder; - private String name; - // used when configuring the number of segments. private int minSegments = -1; private int actualSegments = -1; @@ -277,6 +275,8 @@ public final class ChronicleMapBuilder implements checkSizeIsNotStaticallyKnown(keyBuilder); checkAverageSize(averageKeySize, "key"); this.averageKeySize = averageKeySize; + averageKey = null; + sampleKey = null; return this; } @@ -296,6 +296,7 @@ public final class ChronicleMapBuilder implements checkSizeIsNotStaticallyKnown(keyBuilder); this.averageKey = averageKey; sampleKey = null; + averageKeySize = UNDEFINED_DOUBLE_CONFIG; return this; } @@ -317,11 +318,12 @@ public final class ChronicleMapBuilder implements public ChronicleMapBuilder constantKeySizeBySample(K sampleKey) { this.sampleKey = sampleKey; averageKey = null; + averageKeySize = UNDEFINED_DOUBLE_CONFIG; return this; } private double averageKeySize() { - return averageKeyOrValueSize(averageKeySize, keyBuilder, averageKey); + return averageKeySize = averageKeyOrValueSize(averageKeySize, keyBuilder, averageKey); } /** @@ -340,6 +342,9 @@ public final class ChronicleMapBuilder implements *

If values are of boxed primitive type or {@link Byteable} subclass, i. e. if value size is * known statically, it is automatically accounted and shouldn't be specified by user. * + *

Calling this method clears any previous {@link #constantValueSizeBySample(Object)} and + * {@link #averageValue(Object)} configurations. + * * @param averageValueSize number of bytes, taken by serialized form of values * @return this builder back * @throws IllegalStateException if value size is known statically and shouldn't be @@ -354,6 +359,8 @@ public final class ChronicleMapBuilder implements checkSizeIsNotStaticallyKnown(valueBuilder); checkAverageSize(averageValueSize, "value"); this.averageValueSize = averageValueSize; + averageValue = null; + sampleValue = null; return this; } @@ -378,7 +385,7 @@ public final class ChronicleMapBuilder implements * known statically, it is automatically accounted and shouldn't be specified by user. * *

Calling this method clears any previous {@link #constantValueSizeBySample(Object)} - * configuration. + * and {@link #averageValueSize(double)} configurations. * * @param averageValue the average (by footprint in serialized form) value, is going to be put * into the maps, created by this builder @@ -394,6 +401,7 @@ public final class ChronicleMapBuilder implements checkSizeIsNotStaticallyKnown(valueBuilder); this.averageValue = averageValue; sampleValue = null; + averageValueSize = UNDEFINED_DOUBLE_CONFIG; return this; } @@ -422,7 +430,8 @@ public final class ChronicleMapBuilder implements *

If value size varies, method {@link #averageValue(Object)} or {@link * #averageValueSize(double)} should be called instead of this one. * - *

Calling this method clears any previous {@link #averageValue(Object)} configuration. + *

Calling this method clears any previous {@link #averageValue(Object)} and + * {@link #averageValueSize(double)} configurations. * * @param sampleValue the sample value * @return this builder back @@ -433,23 +442,25 @@ public final class ChronicleMapBuilder implements public ChronicleMapBuilder constantValueSizeBySample(V sampleValue) { this.sampleValue = sampleValue; averageValue = null; + averageValueSize = UNDEFINED_DOUBLE_CONFIG; return this; } double averageValueSize() { - return averageKeyOrValueSize(averageValueSize, valueBuilder, averageValue); + return averageValueSize = + averageKeyOrValueSize(averageValueSize, valueBuilder, averageValue); } - private double averageKeyOrValueSize( - double configuredSize, SerializationBuilder builder, Object average) { - if (average != null) { - builder.maxSize(DEFAULT_KEY_OR_VALUE_SIZE); - return builder.serializationSize(average); - } + private double averageKeyOrValueSize( + double configuredSize, SerializationBuilder builder, E average) { if (isDefined(configuredSize)) return configuredSize; if (builder.constantSizeMarshaller()) return builder.pseudoReadConstantSize(); + if (average != null) { + builder.maxSize(DEFAULT_KEY_OR_VALUE_SIZE); + return builder.serializationSize(average); + } return DEFAULT_KEY_OR_VALUE_SIZE; } @@ -476,7 +487,10 @@ public final class ChronicleMapBuilder implements return this; } - @Override + /** + * @deprecated part of private API, shouldn't be used in the client code + */ + @Deprecated public SerializationBuilder keyBuilder() { return keyBuilder; } @@ -537,11 +551,12 @@ public final class ChronicleMapBuilder implements } /** - * This is needed, if chunkSize = constant entry size is not aligned, for entry alignment to be - * always the same, we should _misalign_ the first chunk. + * @deprecated part of private API, shouldn't be used in the client code */ - @Override + @Deprecated public int segmentEntrySpaceInnerOffset(boolean replicated) { + // This is needed, if chunkSize = constant entry size is not aligned, for entry alignment + // to be always the same, we should _misalign_ the first chunk. if (!constantlySizedEntries()) return 0; return (int) (constantValueSize() % valueAlignment().alignment()); @@ -595,7 +610,10 @@ public final class ChronicleMapBuilder implements return greatestCommonDivisor(b, a % b); } - @Override + /** + * @deprecated part of private API, shouldn't be used in the client code + */ + @Deprecated public long chunkSize(boolean replicated) { if (actualChunkSize > 0) return actualChunkSize; @@ -617,6 +635,7 @@ public final class ChronicleMapBuilder implements double averageChunksPerEntry(boolean replicated) { if (constantlySizedEntries()) return 1.0; + @SuppressWarnings("deprecation") long chunkSize = chunkSize(replicated); // assuming we always has worst internal fragmentation. This affects total segment // entry space which is allocated lazily on Linux (main target platform) @@ -637,15 +656,19 @@ public final class ChronicleMapBuilder implements return this; } - @Override - public int maxChunksPerEntry() { - if (maxChunksPerEntry > 0) - return maxChunksPerEntry; - if (constantlySizedEntries()) { + /** + * @deprecated part of private API, shouldn't be used in the client code + */ + @Deprecated + public int maxChunksPerEntry(boolean replicated) { + if (constantlySizedEntries()) return 1; - } else { - return Integer.MAX_VALUE; - } + @SuppressWarnings("deprecation") + long actualChunksPerSegment = actualChunksPerSegment(replicated); + int result = (int) Math.min(actualChunksPerSegment, (long) Integer.MAX_VALUE); + if (this.maxChunksPerEntry > 0) + result = Math.min(this.maxChunksPerEntry, result); + return result; } private boolean constantlySizedValues() { @@ -719,12 +742,16 @@ public final class ChronicleMapBuilder implements return this; } - @Override + /** + * @deprecated part of private API, shouldn't be used in the client code + */ + @Deprecated public long entriesPerSegment(boolean replicated) { long entriesPerSegment; if (this.entriesPerSegment > 0L) { entriesPerSegment = this.entriesPerSegment; } else { + @SuppressWarnings("deprecation") int actualSegments = actualSegments(replicated); long totalEntries = totalEntriesIfPoorDistribution(actualSegments); entriesPerSegment = divideUpper(totalEntries, actualSegments); @@ -773,7 +800,10 @@ public final class ChronicleMapBuilder implements } } - @Override + /** + * @deprecated part of private API, shouldn't be used in the client code + */ + @Deprecated public long actualChunksPerSegment(boolean replicated) { if (actualChunksPerSegment > 0) return actualChunksPerSegment; @@ -863,7 +893,10 @@ public final class ChronicleMapBuilder implements return this; } - @Override + /** + * @deprecated part of private API, shouldn't be used in the client code + */ + @Deprecated public int actualSegments(boolean replicated) { if (actualSegments > 0) return actualSegments; @@ -952,8 +985,12 @@ public final class ChronicleMapBuilder implements return segments <= maxSegments ? segments : -segments; } - @Override + /** + * @deprecated part of private API, shouldn't be used in the client code + */ + @Deprecated public int segmentHeaderSize(boolean replicated) { + @SuppressWarnings("deprecation") int segments = actualSegments(replicated); // reduce false sharing unless we have a lot of segments. return segments <= 16 * 1024 ? 64 : 32; @@ -994,7 +1031,6 @@ public final class ChronicleMapBuilder implements @Override public String toString() { return "ChronicleMapBuilder{" + - "name=" + name + ", actualSegments=" + pretty(actualSegments) + ", minSegments=" + pretty(minSegments) + ", entriesPerSegment=" + pretty(entriesPerSegment) + @@ -1507,25 +1543,21 @@ public final class ChronicleMapBuilder implements } void preMapConstruction(boolean replicated) { - keyBuilder.objectSerializer(acquireObjectSerializer(JDKObjectSerializer.INSTANCE)); - valueBuilder.objectSerializer(acquireObjectSerializer(JDKObjectSerializer.INSTANCE)); - - double largeKeySize = averageKeySize(); - if (!constantlySizedKeys()) - largeKeySize *= figureBufferAllocationFactor(); - keyBuilder.maxSize(round(largeKeySize)); - double largeValueSize = averageValueSize(); - if (!constantlySizedValues()) - largeValueSize *= figureBufferAllocationFactor(); - valueBuilder.maxSize(round(largeValueSize)); - - if (sampleKey != null) - keyBuilder.constantSizeBySample(sampleKey); - if (sampleValue != null) - valueBuilder.constantSizeBySample(sampleValue); + preMapConstruction(replicated, keyBuilder, averageKeySize(), sampleKey); + preMapConstruction(replicated, valueBuilder, averageValueSize(), sampleValue); stateChecks(); } + private void preMapConstruction( + boolean replicated, SerializationBuilder builder, double averageSize, E sample) { + builder.objectSerializer(acquireObjectSerializer(JDKObjectSerializer.INSTANCE)); + if (sample != null) { + builder.constantSizeBySample(sample); + } else { + builder.maxSize(bufferSize(builder, averageSize, replicated)); + } + } + private void stateChecks() { if (strictStateChecks) { if (entries < 0) @@ -1574,11 +1606,21 @@ public final class ChronicleMapBuilder implements return map; } - private int figureBufferAllocationFactor() { + private long bufferSize(SerializationBuilder builder, double averageSize, boolean replicated) { + if (builder.constantSizeMarshaller()) + return round(ceil(averageSize)); + + int maxChunksPerEntry = maxChunksPerEntry(replicated); + // if maxChunksPerEntry is Integer.MAX_VALUE, we, of cause, + // are not going to allocate such big buffers + int limitedMaxChunksPerEntry = Math.min(64, maxChunksPerEntry); + long limitedMaxEntrySize = limitedMaxChunksPerEntry * chunkSize(replicated); + // if expected map size is about 1000, seems rather wasteful to allocate // key and value serialization buffers each x64 of expected entry size.. - return (int) Math.min(Math.max(2L, entries() >> 10), - Math.min(64, maxChunksPerEntry())); + long limitFactor = Math.max(2L, entries() >> 10); + + return Math.min(round(ceil(limitFactor * averageSize)), limitedMaxEntrySize); } /**