mirror of
https://github.com/OpenHFT/Chronicle-Map.git
synced 2021-09-13 01:26:12 +00:00
Removed ChronicleHashBuilderImpl and ChronicleMapBuilder minor cleanup
This commit is contained in:
@@ -100,6 +100,9 @@ public interface ChronicleHashBuilder<K, H extends ChronicleHash<K, ?, ?, ?>,
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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<K, H extends ChronicleHash<K, ?, ?, ?>,
|
||||
* <p>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.
|
||||
*
|
||||
* <p>Calling this method clears any previous {@link #constantKeySizeBySample(Object)}
|
||||
* configuration.
|
||||
* <p>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<K, H extends ChronicleHash<K, ?, ?, ?>,
|
||||
* <p>If key size varies, method {@link #averageKeySize(double)} should be called instead of
|
||||
* this one.
|
||||
*
|
||||
* <p>Calling this method clears any previous {@link #averageKey(Object)} configuration.
|
||||
* <p>Calling this method clears any previous {@link #averageKey(Object)} and
|
||||
* {@link #averageKeySize(double)} configurations.
|
||||
*
|
||||
* @param sampleKey the sample key
|
||||
* @return this builder back
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<K, H extends ChronicleHash<K, ?, ?, ?>,
|
||||
B extends ChronicleHashBuilder<K, H, B>> extends ChronicleHashBuilder<K, H, B> {
|
||||
|
||||
SerializationBuilder<K> 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);
|
||||
}
|
||||
@@ -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<K, KI, MKI extends MetaBytesInterop<K
|
||||
transient long segmentHeadersOffset;
|
||||
transient long segmentsOffset;
|
||||
|
||||
public VanillaChronicleHash(ChronicleHashBuilderImpl<K, ?, ?> builder, boolean replicated) {
|
||||
@SuppressWarnings("deprecation")
|
||||
public VanillaChronicleHash(ChronicleMapBuilder<K, ?> builder, boolean replicated) {
|
||||
// Version
|
||||
dataFileVersion = BuildVersion.version();
|
||||
|
||||
@@ -126,7 +128,7 @@ public abstract class VanillaChronicleHash<K, KI, MKI extends MetaBytesInterop<K
|
||||
entriesPerSegment = builder.entriesPerSegment(replicated);
|
||||
|
||||
chunkSize = builder.chunkSize(replicated);
|
||||
maxChunksPerEntry = builder.maxChunksPerEntry();
|
||||
maxChunksPerEntry = builder.maxChunksPerEntry(replicated);
|
||||
actualChunksPerSegment = builder.actualChunksPerSegment(replicated);
|
||||
|
||||
// Precomputed offsets and sizes for fast Context init
|
||||
|
||||
@@ -18,7 +18,6 @@ package net.openhft.chronicle.map;
|
||||
|
||||
import net.openhft.chronicle.hash.ChronicleHashBuilder;
|
||||
import net.openhft.chronicle.hash.ChronicleHashInstanceBuilder;
|
||||
import net.openhft.chronicle.hash.impl.ChronicleHashBuilderImpl;
|
||||
import net.openhft.chronicle.hash.impl.stage.entry.HashLookup;
|
||||
import net.openhft.chronicle.hash.replication.*;
|
||||
import net.openhft.chronicle.hash.serialization.*;
|
||||
@@ -54,6 +53,7 @@ import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static java.lang.Math.ceil;
|
||||
import static java.lang.Math.round;
|
||||
import static net.openhft.chronicle.hash.impl.util.Objects.builderEquals;
|
||||
import static net.openhft.chronicle.map.DefaultSpi.mapEntryOperations;
|
||||
@@ -103,7 +103,7 @@ import static net.openhft.lang.model.DataValueGenerator.firstPrimitiveFieldType;
|
||||
* @see ChronicleSetBuilder
|
||||
*/
|
||||
public final class ChronicleMapBuilder<K, V> implements
|
||||
ChronicleHashBuilderImpl<K, ChronicleMap<K, V>, ChronicleMapBuilder<K, V>>,
|
||||
ChronicleHashBuilder<K, ChronicleMap<K, V>, ChronicleMapBuilder<K, V>>,
|
||||
MapBuilder<ChronicleMapBuilder<K, V>>, Serializable {
|
||||
|
||||
static final byte UDP_REPLICATION_MODIFICATION_ITERATOR_ID = (byte) 127;
|
||||
@@ -132,8 +132,6 @@ public final class ChronicleMapBuilder<K, V> implements
|
||||
SerializationBuilder<K> keyBuilder;
|
||||
SerializationBuilder<V> 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<K, V> implements
|
||||
checkSizeIsNotStaticallyKnown(keyBuilder);
|
||||
checkAverageSize(averageKeySize, "key");
|
||||
this.averageKeySize = averageKeySize;
|
||||
averageKey = null;
|
||||
sampleKey = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -296,6 +296,7 @@ public final class ChronicleMapBuilder<K, V> implements
|
||||
checkSizeIsNotStaticallyKnown(keyBuilder);
|
||||
this.averageKey = averageKey;
|
||||
sampleKey = null;
|
||||
averageKeySize = UNDEFINED_DOUBLE_CONFIG;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -317,11 +318,12 @@ public final class ChronicleMapBuilder<K, V> implements
|
||||
public ChronicleMapBuilder<K, V> 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<K, V> implements
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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<K, V> implements
|
||||
checkSizeIsNotStaticallyKnown(valueBuilder);
|
||||
checkAverageSize(averageValueSize, "value");
|
||||
this.averageValueSize = averageValueSize;
|
||||
averageValue = null;
|
||||
sampleValue = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -378,7 +385,7 @@ public final class ChronicleMapBuilder<K, V> implements
|
||||
* known statically, it is automatically accounted and shouldn't be specified by user.
|
||||
*
|
||||
* <p>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<K, V> implements
|
||||
checkSizeIsNotStaticallyKnown(valueBuilder);
|
||||
this.averageValue = averageValue;
|
||||
sampleValue = null;
|
||||
averageValueSize = UNDEFINED_DOUBLE_CONFIG;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -422,7 +430,8 @@ public final class ChronicleMapBuilder<K, V> implements
|
||||
* <p>If value size varies, method {@link #averageValue(Object)} or {@link
|
||||
* #averageValueSize(double)} should be called instead of this one.
|
||||
*
|
||||
* <p>Calling this method clears any previous {@link #averageValue(Object)} configuration.
|
||||
* <p>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<K, V> implements
|
||||
public ChronicleMapBuilder<K, V> 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 <E> double averageKeyOrValueSize(
|
||||
double configuredSize, SerializationBuilder<E> 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<K, V> implements
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
/**
|
||||
* @deprecated part of private API, shouldn't be used in the client code
|
||||
*/
|
||||
@Deprecated
|
||||
public SerializationBuilder<K> keyBuilder() {
|
||||
return keyBuilder;
|
||||
}
|
||||
@@ -537,11 +551,12 @@ public final class ChronicleMapBuilder<K, V> 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<K, V> 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<K, V> 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<K, V> 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<K, V> 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<K, V> 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<K, V> 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<K, V> 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<K, V> 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<K, V> 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 <E> void preMapConstruction(
|
||||
boolean replicated, SerializationBuilder<E> 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<K, V> 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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user