Merge remote-tracking branch 'origin/master'

This commit is contained in:
Rob Austin
2014-11-10 16:21:34 +00:00
13 changed files with 135 additions and 218 deletions
+1 -1
View File
@@ -46,7 +46,7 @@
<dependency>
<groupId>net.openhft</groupId>
<artifactId>lang</artifactId>
<version>6.4.12</version>
<version>6.4.13-SNAPSHOT</version>
</dependency>
<dependency>
@@ -26,7 +26,7 @@ import net.openhft.chronicle.hash.serialization.SizeMarshaller;
import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop;
import net.openhft.chronicle.hash.serialization.internal.MetaBytesWriter;
import net.openhft.chronicle.hash.serialization.internal.MetaProvider;
import net.openhft.chronicle.map.utils.MultiMapFactory;
import net.openhft.chronicle.map.MultiMapFactory;
import net.openhft.chronicle.set.ChronicleSetBuilder;
import net.openhft.lang.Maths;
import net.openhft.lang.io.ByteBufferBytes;
@@ -372,10 +372,8 @@ public abstract class AbstractChronicleMapBuilder<K, V,
if (segments == 1)
return entries;
double poorDistEntriesScale = Math.log(segments) * entries;
if (segments <= 8)
return Math.min(entries * segments,
(long) (entries + poorDistEntriesScale * 0.11 + segments * 8)); // 11% was min for tests
return (long) (entries + poorDistEntriesScale * 0.11 + 80); // 11% was min for tests
return Math.min(entries * segments,
(long) (entries + poorDistEntriesScale * 0.14 + 32)); // 12% was min for tests
}
@Override
@@ -390,24 +388,22 @@ public abstract class AbstractChronicleMapBuilder<K, V,
}
private int estimateSegments() {
for (int power = 1; power < 64; power *= 2) {
if (entries <= power * power * power)
return power;
}
long size = (entrySize + 32) * entries;
if (size < 10L * 1000 * 1000) // 10 MB
return 64;
if (size < 100L * 1000 * 1000) // 100 MB
return 128;
if (size < 400L * 1000 * 1000) // 400 MB
return 256;
if (size < 1L * 1000 * 1000 * 1000) // 1 GB
return (int) Math.min(Maths.nextPower2(entries / 32, 1), estimateSegementBasedOnSize());
}
private int estimateSegementBasedOnSize() {
// based on entries with multimap of 100 bytes.
long size = (long) (Math.log10(entrySize + 32) / 2 * entries);
if (size < 10 * 1000)
return 512;
if (size < 10L * 1000 * 1000 * 1000) // 10 GB
if (size < 100 * 1000)
return 1024;
if (size < 100L * 1000 * 1000 * 1000) // 100 GB
if (size < 1000 * 1000)
return 2048;
return 4096;
if (size < 10 * 1000 * 1000)
return 4096;
return 8192;
}
@Override
@@ -439,6 +435,17 @@ public abstract class AbstractChronicleMapBuilder<K, V,
return segments <= maxSegments ? segments : -segments;
}
int segmentHeaderSize() {
int segments = actualSegments();
// reduce false sharing unless we have a lot of segments.
return segments <= 8192 ? 128 : 64;
}
MultiMapFactory multiMapFactory() {
return MultiMapFactory.forCapacity(actualEntriesPerSegment());
}
public B lockTimeOut(long lockTimeOut, TimeUnit unit) {
this.lockTimeOut = lockTimeOut;
lockTimeOutUnit = unit;
@@ -933,15 +940,5 @@ public abstract class AbstractChronicleMapBuilder<K, V,
return (int) Math.min(Math.max(2L, entries() >> 10),
VanillaChronicleMap.MAX_ENTRY_OVERSIZE_FACTOR);
}
int segmentHeaderSize() {
int segments = actualSegments();
// reduce false sharing unless we have a lot of segments.
return segments <= 8192 ? 64 : 16;
}
public MultiMapFactory multiMapFactory() {
return MultiMapFactory.forCapacity(actualEntriesPerSegment());
}
}
@@ -16,7 +16,7 @@
* limitations under the License.
*/
package net.openhft.chronicle.map.utils;
package net.openhft.chronicle.map;
import net.openhft.lang.collection.ATSDirectBitSet;
import net.openhft.lang.collection.DirectBitSet;
@@ -28,7 +28,7 @@ import static net.openhft.lang.Maths.isPowerOf2;
/**
* Supports a simple interface for int -> int[] off heap.
*/
class VanillaI24I24MultiMap implements MultiMap {
class Int24Int24MultiMap implements MultiMap {
static final int MAX_CAPACITY = (1 << 24);
@@ -48,8 +48,8 @@ class VanillaI24I24MultiMap implements MultiMap {
private int searchHash = -1;
private int searchPos = -1;
public VanillaI24I24MultiMap(long minCapacity) {
capacity = (int) VanillaIntIntMultiMap.multiMapCapacity(minCapacity);
public Int24Int24MultiMap(long minCapacity) {
capacity = (int) IntIntMultiMap.multiMapCapacity(minCapacity);
capacityMask = capacity - 1;
capacityMod2 = indexToPos(capacity - 1);
bytes = DirectStore.allocateLazy(indexToPos(capacity)).bytes();
@@ -57,7 +57,7 @@ class VanillaI24I24MultiMap implements MultiMap {
clear();
}
public VanillaI24I24MultiMap(Bytes multiMapBytes, Bytes multiMapBitSetBytes) {
public Int24Int24MultiMap(Bytes multiMapBytes, Bytes multiMapBitSetBytes) {
capacity = (int) Math.min(MAX_CAPACITY, (multiMapBytes.capacity() / ENTRY_SIZE));
assert capacity <= MAX_CAPACITY;
capacityMask = capacity - 1;
@@ -67,21 +67,21 @@ class VanillaI24I24MultiMap implements MultiMap {
}
/**
* @param minCapacity as in {@link #VanillaI24I24MultiMap(long)} constructor
* @return size of {@link Bytes} to provide to {@link #VanillaI24I24MultiMap(Bytes, Bytes)}
* @param minCapacity as in {@link #Int24Int24MultiMap(long)} constructor
* @return size of {@link Bytes} to provide to {@link #Int24Int24MultiMap(Bytes, Bytes)}
* constructor as the first argument
*/
public static long sizeInBytes(long minCapacity) {
return indexToPos((int) VanillaIntIntMultiMap.multiMapCapacity(minCapacity));
return indexToPos((int) IntIntMultiMap.multiMapCapacity(minCapacity));
}
/**
* @param minCapacity as in {@link #VanillaI24I24MultiMap(long)} constructor
* @return size of {@link Bytes} to provide to {@link #VanillaI24I24MultiMap(Bytes, Bytes)}
* @param minCapacity as in {@link #Int24Int24MultiMap(long)} constructor
* @return size of {@link Bytes} to provide to {@link #Int24Int24MultiMap(Bytes, Bytes)}
* constructor as the second argument
*/
public static long sizeOfBitSetInBytes(long minCapacity) {
return (int) (Math.max(VanillaIntIntMultiMap.multiMapCapacity(minCapacity), 64L) * 6L + 63) / 64;
return (int) (Math.max(IntIntMultiMap.multiMapCapacity(minCapacity), 64L) * 6L + 63) / 64;
}
public static ATSDirectBitSet newPositions(int capacity) {
@@ -16,7 +16,7 @@
* limitations under the License.
*/
package net.openhft.chronicle.map.utils;
package net.openhft.chronicle.map;
import net.openhft.lang.Maths;
import net.openhft.lang.collection.ATSDirectBitSet;
@@ -29,7 +29,7 @@ import static net.openhft.lang.Maths.isPowerOf2;
/**
* Supports a simple interface for int -> int[] off heap.
*/
class VanillaIntIntMultiMap implements MultiMap {
class IntIntMultiMap implements MultiMap {
static final long MAX_CAPACITY = (1L << 32);
@@ -59,7 +59,7 @@ class VanillaIntIntMultiMap implements MultiMap {
private long searchHash = -1L;
private long searchPos = -1L;
public VanillaIntIntMultiMap(long minCapacity) {
public IntIntMultiMap(long minCapacity) {
capacity = multiMapCapacity(minCapacity);
capacityMask = capacity - 1L;
capacityMask2 = indexToPos(capacity - 1L);
@@ -68,7 +68,7 @@ class VanillaIntIntMultiMap implements MultiMap {
clear();
}
public VanillaIntIntMultiMap(Bytes multiMapBytes, Bytes multiMapBitSetBytes) {
public IntIntMultiMap(Bytes multiMapBytes, Bytes multiMapBitSetBytes) {
capacity = multiMapBytes.capacity() / ENTRY_SIZE;
assert capacity == Maths.nextPower2(capacity, 16L);
capacityMask = capacity - 1L;
@@ -78,8 +78,8 @@ class VanillaIntIntMultiMap implements MultiMap {
}
/**
* @param minCapacity as in {@link #VanillaIntIntMultiMap(long)} constructor
* @return size of {@link Bytes} to provide to {@link #VanillaIntIntMultiMap(Bytes, Bytes)}
* @param minCapacity as in {@link #IntIntMultiMap(long)} constructor
* @return size of {@link Bytes} to provide to {@link #IntIntMultiMap(Bytes, Bytes)}
* constructor as the first argument
*/
public static long sizeInBytes(long minCapacity) {
@@ -87,8 +87,8 @@ class VanillaIntIntMultiMap implements MultiMap {
}
/**
* @param minCapacity as in {@link #VanillaIntIntMultiMap(long)} constructor
* @return size of {@link Bytes} to provide to {@link #VanillaIntIntMultiMap(Bytes, Bytes)}
* @param minCapacity as in {@link #IntIntMultiMap(long)} constructor
* @return size of {@link Bytes} to provide to {@link #IntIntMultiMap(Bytes, Bytes)}
* constructor as the second argument
*/
public static long sizeOfBitSetInBytes(long minCapacity) {
@@ -14,14 +14,14 @@
* limitations under the License.
*/
package net.openhft.chronicle.map.utils;
package net.openhft.chronicle.map;
import net.openhft.lang.collection.DirectBitSet;
/**
* This is only used to store keys and positions, but it could store int/int key/values for another purpose.
*/
public interface MultiMap {
interface MultiMap {
/**
* @return gets all the active positions as a bitset
@@ -16,7 +16,7 @@
* limitations under the License.
*/
package net.openhft.chronicle.map.utils;
package net.openhft.chronicle.map;
import net.openhft.lang.io.NativeBytes;
@@ -25,65 +25,65 @@ import net.openhft.lang.io.NativeBytes;
*
* In future we might support I32 -> I16 or similar.
*/
public enum MultiMapFactory {
enum MultiMapFactory {
I16 {
@Override
public long sizeInBytes(long minCapacity) {
return VanillaShortShortMultiMap.sizeInBytes(minCapacity);
return ShortShortMultiMap.sizeInBytes(minCapacity);
}
@Override
public long sizeOfBitSetInBytes(long minCapacity) {
return VanillaShortShortMultiMap.sizeOfBitSetInBytes(minCapacity);
return ShortShortMultiMap.sizeOfBitSetInBytes(minCapacity);
}
@Override
public MultiMap create(NativeBytes bytes, NativeBytes bitSetBytes) {
return new VanillaShortShortMultiMap(bytes, bitSetBytes);
return new ShortShortMultiMap(bytes, bitSetBytes);
}
},
I24 {
@Override
public long sizeInBytes(long minCapacity) {
return VanillaI24I24MultiMap.sizeInBytes(minCapacity);
return Int24Int24MultiMap.sizeInBytes(minCapacity);
}
@Override
public long sizeOfBitSetInBytes(long minCapacity) {
return VanillaI24I24MultiMap.sizeOfBitSetInBytes(minCapacity);
return Int24Int24MultiMap.sizeOfBitSetInBytes(minCapacity);
}
@Override
public MultiMap create(NativeBytes bytes, NativeBytes bitSetBytes) {
return new VanillaI24I24MultiMap(bytes, bitSetBytes);
return new Int24Int24MultiMap(bytes, bitSetBytes);
}
},
I32 {
@Override
public long sizeInBytes(long minCapacity) {
return VanillaIntIntMultiMap.sizeInBytes(minCapacity);
return IntIntMultiMap.sizeInBytes(minCapacity);
}
@Override
public long sizeOfBitSetInBytes(long minCapacity) {
return VanillaIntIntMultiMap.sizeOfBitSetInBytes(minCapacity);
return IntIntMultiMap.sizeOfBitSetInBytes(minCapacity);
}
@Override
public MultiMap create(NativeBytes bytes, NativeBytes bitSetBytes) {
return new VanillaIntIntMultiMap(bytes, bitSetBytes);
return new IntIntMultiMap(bytes, bitSetBytes);
}
};
public static final long I16_MAX_CAPACITY = VanillaShortShortMultiMap.MAX_CAPACITY;
public static final long MAX_CAPACITY = VanillaIntIntMultiMap.MAX_CAPACITY;
public static final long I16_MAX_CAPACITY = ShortShortMultiMap.MAX_CAPACITY;
public static final long MAX_CAPACITY = IntIntMultiMap.MAX_CAPACITY;
public static MultiMapFactory forCapacity(long capacity) {
if (capacity <= VanillaShortShortMultiMap.MAX_CAPACITY)
if (capacity <= ShortShortMultiMap.MAX_CAPACITY)
return I16;
// if (capacity <= VanillaI24I24MultiMap.MAX_CAPACITY)
// if (capacity <= Int24Int24MultiMap.MAX_CAPACITY)
// return I24;
if (capacity <= VanillaIntIntMultiMap.MAX_CAPACITY)
if (capacity <= IntIntMultiMap.MAX_CAPACITY)
return I32;
throw new IllegalArgumentException("Capacity " + capacity + " not supported");
}
@@ -23,7 +23,7 @@ import net.openhft.chronicle.hash.replication.TimeProvider;
import net.openhft.chronicle.hash.serialization.BytesReader;
import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop;
import net.openhft.chronicle.hash.serialization.internal.MetaBytesWriter;
import net.openhft.chronicle.map.utils.MultiMap;
import net.openhft.chronicle.map.MultiMap;
import net.openhft.lang.Maths;
import net.openhft.lang.collection.ATSDirectBitSet;
import net.openhft.lang.io.Bytes;
@@ -273,7 +273,7 @@ final class ReplicatedChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
}
@Override
<T extends Context> T lookupUsing(K key, V value, LockType lockTypeType) {
<T extends Context> T lookupUsing(K key, V usingValue, LockType lockType, boolean mustReuseValue) {
checkKey(key);
ThreadLocalCopies copies = keyInteropProvider.getCopies(null);
KI keyWriter = keyInteropProvider.get(copies, originalKeyInterop);
@@ -284,24 +284,26 @@ final class ReplicatedChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
int segmentNum = getSegment(hash);
long segmentHash = segmentHash(hash);
boolean create = lockTypeType == LockType.WRITE_LOCK;
boolean create = lockType == LockType.WRITE_LOCK;
Segment segment = segment(segmentNum);
MutableLockedEntry<K, V, MKI, KI> lock = (lockTypeType == LockType.WRITE_LOCK)
MutableLockedEntry<K, V, MKI, KI> lock = (lockType == LockType.WRITE_LOCK)
? segment.writeLock()
: segment.readLock();
V v = segment.acquireWithoutLock(copies, metaKeyWriter, keyWriter, key,
value,
usingValue,
segmentHash, create, create ? timeProvider.currentTimeMillis() : 0L);
checkReallyUsingValue(usingValue, mustReuseValue, v);
lock.copies = copies;
lock.metaKeyInterop = metaKeyWriter;
lock.keyInterop = keyWriter;
lock.segmentHash = segmentHash;
if (!isNativeValueClass && lockTypeType == LockType.WRITE_LOCK && v == null)
v = value;
if (!isNativeValueClass && lockType == LockType.WRITE_LOCK && v == null)
v = usingValue;
lock.value(v);
lock.key(key);
@@ -16,7 +16,7 @@
* limitations under the License.
*/
package net.openhft.chronicle.map.utils;
package net.openhft.chronicle.map;
import net.openhft.lang.collection.ATSDirectBitSet;
@@ -24,13 +24,13 @@ import net.openhft.lang.collection.DirectBitSet;
import net.openhft.lang.io.Bytes;
import net.openhft.lang.io.DirectStore;
import static net.openhft.chronicle.map.utils.VanillaIntIntMultiMap.multiMapCapacity;
import static net.openhft.chronicle.map.IntIntMultiMap.multiMapCapacity;
import static net.openhft.lang.Maths.isPowerOf2;
/**
* Supports a simple interface for int -> int[] off heap.
*/
class VanillaShortShortMultiMap implements MultiMap {
class ShortShortMultiMap implements MultiMap {
static final long MAX_CAPACITY = (1L << 16);
@@ -47,7 +47,7 @@ class VanillaShortShortMultiMap implements MultiMap {
private long searchHash = -1L;
private long searchPos = -1L;
public VanillaShortShortMultiMap(long minCapacity) {
public ShortShortMultiMap(long minCapacity) {
assert minCapacity <= MAX_CAPACITY;
long capacity = multiMapCapacity(minCapacity);
assert isPowerOf2(capacity);
@@ -55,11 +55,11 @@ class VanillaShortShortMultiMap implements MultiMap {
capacityMask = capacity - 1L;
capacityMask2 = (capacity - 1L) * ENTRY_SIZE;
bytes = DirectStore.allocateLazy(capacity * ENTRY_SIZE).bytes();
positions = VanillaIntIntMultiMap.newPositions(capacity);
positions = IntIntMultiMap.newPositions(capacity);
clear();
}
public VanillaShortShortMultiMap(Bytes multiMapBytes, Bytes multiMapBitSetBytes) {
public ShortShortMultiMap(Bytes multiMapBytes, Bytes multiMapBitSetBytes) {
long capacity = multiMapBytes.capacity() / ENTRY_SIZE;
assert isPowerOf2(capacity);
assert (capacity / 2L) <= MAX_CAPACITY;
@@ -71,8 +71,8 @@ class VanillaShortShortMultiMap implements MultiMap {
}
/**
* @param minCapacity as in {@link #VanillaShortShortMultiMap(long)} constructor
* @return size of {@link Bytes} to provide to {@link #VanillaShortShortMultiMap(Bytes, Bytes)}
* @param minCapacity as in {@link #ShortShortMultiMap(long)} constructor
* @return size of {@link Bytes} to provide to {@link #ShortShortMultiMap(Bytes, Bytes)}
* constructor as the first argument
*/
public static long sizeInBytes(long minCapacity) {
@@ -80,14 +80,14 @@ class VanillaShortShortMultiMap implements MultiMap {
}
/**
* @param minCapacity as in {@link #VanillaShortShortMultiMap(long)} constructor
* @return size of {@link Bytes} to provide to {@link #VanillaShortShortMultiMap(Bytes, Bytes)}
* @param minCapacity as in {@link #ShortShortMultiMap(long)} constructor
* @return size of {@link Bytes} to provide to {@link #ShortShortMultiMap(Bytes, Bytes)}
* constructor as the second argument
*/
public static long sizeOfBitSetInBytes(long minCapacity) {
return VanillaIntIntMultiMap.sizeOfBitSetInBytes(minCapacity);
return IntIntMultiMap.sizeOfBitSetInBytes(minCapacity);
}
private void checkValueForPut(long value) {
@@ -183,7 +183,7 @@ class VanillaShortShortMultiMap implements MultiMap {
if (entryToShift == UNSET_ENTRY)
break;
long insertPos = pos(key(entryToShift));
// see comment in VanillaIntIntMultiMap
// see comment in IntIntMultiMap
boolean cond1 = insertPos <= posToRemove;
boolean cond2 = posToRemove <= posToShift;
if ((cond1 && cond2) ||
@@ -25,8 +25,6 @@ import net.openhft.chronicle.hash.serialization.SizeMarshaller;
import net.openhft.chronicle.hash.serialization.internal.MetaBytesInterop;
import net.openhft.chronicle.hash.serialization.internal.MetaBytesWriter;
import net.openhft.chronicle.hash.serialization.internal.MetaProvider;
import net.openhft.chronicle.map.utils.MultiMap;
import net.openhft.chronicle.map.utils.MultiMapFactory;
import net.openhft.lang.collection.DirectBitSet;
import net.openhft.lang.collection.SingleThreadedDirectBitSet;
import net.openhft.lang.io.*;
@@ -357,7 +355,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
public V get(Object key) {
try (Context<K, V> entry = lookupUsing((K) key, null,
LockType.READ_LOCK)) {
LockType.READ_LOCK, false)) {
return entry.value();
}
}
@@ -366,7 +364,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
public V getUsing(K key, V usingValue) {
try (Context<K, V> entry = lookupUsing(key, usingValue,
LockType.READ_LOCK)) {
LockType.READ_LOCK, false)) {
return entry.value();
}
}
@@ -374,20 +372,21 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
@NotNull
@Override
public WriteContext<K, V> acquireUsingLocked(@NotNull K key, @NotNull V usingValue) {
return this.lookupUsing(key, usingValue, LockType.WRITE_LOCK);
return this.lookupUsing(key, usingValue, LockType.WRITE_LOCK, true);
}
@NotNull
@Override
public ReadContext<K, V> getUsingLocked(@NotNull K key, @NotNull V usingValue) {
return this.lookupUsing(key, usingValue, LockType.READ_LOCK);
return this.lookupUsing(key, usingValue, LockType.READ_LOCK, true);
}
@Override
public V acquireUsing(@NotNull K key, @NotNull V usingValue) {
try (WriteContext<K, V> kvContext = lookupUsing(key, usingValue, LockType.WRITE_LOCK)) {
try (WriteContext<K, V> kvContext =
lookupUsing(key, usingValue, LockType.WRITE_LOCK, false)) {
if (!isNativeValueClass)
kvContext.dontPutOnClose();
@@ -397,7 +396,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
}
<T extends Context> T lookupUsing(K key, V value, LockType lockTypeType) {
<T extends Context> T lookupUsing(K key, V usingValue, LockType lockType, boolean mustReuseValue) {
checkKey(key);
ThreadLocalCopies copies = keyInteropProvider.getCopies(null);
KI keyInterop = keyInteropProvider.get(copies, originalKeyInterop);
@@ -409,20 +408,22 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
long segmentHash = segmentHash(hash);
Segment segment = segments[segmentNum];
MutableLockedEntry<K, V, MKI, KI> lock = (lockTypeType == LockType.WRITE_LOCK)
MutableLockedEntry<K, V, MKI, KI> lock = (lockType == LockType.WRITE_LOCK)
? segment.writeLock()
: segment.readLock();
V v = segment.acquireWithoutLock(copies, metaKeyInterop, keyInterop, key, value,
segmentHash, lockTypeType == LockType.WRITE_LOCK);
V v = segment.acquireWithoutLock(copies, metaKeyInterop, keyInterop, key, usingValue,
segmentHash, lockType == LockType.WRITE_LOCK);
checkReallyUsingValue(usingValue, mustReuseValue, v);
lock.copies = copies;
lock.metaKeyInterop = metaKeyInterop;
lock.keyInterop = keyInterop;
lock.segmentHash = segmentHash;
if (!isNativeValueClass && lockTypeType == LockType.WRITE_LOCK && v == null)
v = value;
if (!isNativeValueClass && lockType == LockType.WRITE_LOCK && v == null)
v = usingValue;
lock.value(v);
lock.key(key);
@@ -431,6 +432,12 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
}
void checkReallyUsingValue(V usingValue, boolean mustReuseValue, V returnedValue) {
if (mustReuseValue && returnedValue != null && returnedValue != usingValue)
throw new IllegalArgumentException("acquireUsingLocked/getUsingLocked MUST reuse given " +
"values. Given value" + usingValue + " cannot be reused to read " + returnedValue);
}
@Override
public boolean containsKey(final Object k) {
checkKey(k);
@@ -849,17 +856,7 @@ class VanillaChronicleMap<K, KI, MKI extends MetaBytesInterop<K, KI>,
}
V acquireWithoutLock(ThreadLocalCopies copies, MKI metaKeyInterop, KI keyInterop, K key, V usingValue,
long hash2, boolean create) {
V v = acquire0(copies, metaKeyInterop, keyInterop, key, usingValue, hash2, false);
if (create && v == null)
v = acquire0(copies, metaKeyInterop, keyInterop, key, usingValue, hash2, true);
return v;
}
V acquire0(ThreadLocalCopies copies, MKI metaKeyInterop, KI keyInterop, K key, V usingValue,
long hash2, boolean create) {
long keySize = metaKeyInterop.size(keyInterop, key);
MultiStoreBytes entry = acquireTmpBytes();
long offset = searchKey(keyInterop, metaKeyInterop, key, keySize, hash2, entry,
@@ -1,83 +0,0 @@
/*
* Copyright 2014 Higher Frequency Trading
*
* http://www.higherfrequencytrading.com
*
* Licensed 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 net.openhft.chronicle.map.utils;
import net.openhft.lang.collection.DirectBitSet;
/**
* This is only used to store keys and positions, but it could store int/int key/values for another purpose.
*/
interface IntIntMultiMap {
/**
* @return gets all the active positions as a bitset
*/
DirectBitSet getPositions();
/**
* Add an entry. Allow duplicate hashes, but not key/position pairs.
*
* @param key to add
* @param value to add
*/
void put(int key, int value);
/**
* Remove a key/value pair.
*
* @param key to remove
* @param value to remove
* @return whether a match was found.
*/
boolean remove(int key, int value);
boolean replace(int key, int oldValue, int newValue);
/**
* Used for start a search for a given key
*
* @return normalized key value, better to be used in subsequent calls
*/
int startSearch(int key);
int getSearchHash();
/**
* Used for getting the next position for a given key
*
* @return the next position for the last search or negative value
*/
int nextPos();
void removePrevPos();
void replacePrevPos(int newValue);
void putAfterFailedSearch(int value);
void clear();
void forEach(EntryConsumer action);
static interface EntryConsumer {
void accept(int key, int value);
}
}
@@ -576,7 +576,7 @@ public class ChronicleMapTest {
InstantiationException, InterruptedException, ExecutionException {
// int runs = Integer.getInteger("runs", 10);
int procs = Runtime.getRuntime().availableProcessors();
int threads = procs * 2; // runs > 100 ? procs / 2 : procs;
int threads = procs * 3;
ExecutorService es = Executors.newFixedThreadPool(procs);
for (int runs : new int[]{10, 50, 250, 500, 1000, 2500}) {
// JAVA 8 produces more garbage than previous versions for internal work.
@@ -585,6 +585,7 @@ public class ChronicleMapTest {
OffHeapUpdatableChronicleMapBuilder<CharSequence, LongValue> builder = OffHeapUpdatableChronicleMapBuilder
.of(CharSequence.class, LongValue.class)
.entries(entries)
.actualSegments(8 * 1024)
.entryAndValueAlignment(OF_8_BYTES)
.entrySize(24);
@@ -1362,7 +1363,6 @@ public class ChronicleMapTest {
// check that the entry was removed
try (ReadContext<?, LongValue> context = map.getUsingLocked("one", value)) {
assert value == context.value();
assertEquals(false, context.present());
assertEquals(null, context.value());
}
@@ -1389,12 +1389,13 @@ public class ChronicleMapTest {
}
@Test(expected = IllegalAccessException.class)
@Test(expected = IllegalArgumentException.class)
public void testAcquireUsingLockedWithString() throws IOException {
ChronicleMapBuilder<CharSequence, String> builder = ChronicleMapBuilder
.of(CharSequence.class, String.class)
.entries(1000)
.defaultValue("")
.entrySize(16);
@@ -53,7 +53,7 @@ public class EntryCountMapTest {
throws IOException {
OffHeapUpdatableChronicleMapBuilder<CharSequence, LongValue> mapBuilder = OffHeapUpdatableChronicleMapBuilder.of(CharSequence.class, LongValue.class)
.entries(entries)
.minSegments(segments)
.actualSegments(segments)
.entrySize(entrySize)
.entryAndValueAlignment(alignment);
return mapBuilder.createPersistedTo(getPersistenceFile());
@@ -103,33 +103,33 @@ public class EntryCountMapTest {
testEntriesMaxSize(s, 2000, 3100, i);
testEntriesMaxSize(s, 4000, 5100, i);
testEntriesMaxSize(s, 5000, 7100, i);
testEntriesMaxSize(s, 8000, 10200, i);
testEntriesMaxSize(s, 12000, 16000, i);
testEntriesMaxSize(s, 16000, 21300, i);
testEntriesMaxSize(s, 8000, 11000, i);
testEntriesMaxSize(s, 12000, 17000, i);
testEntriesMaxSize(s, 16000, 22000, i);
s = 32;
testEntriesMaxSize(s, 2000, 3900, i);
testEntriesMaxSize(s, 4000, 5900, i);
testEntriesMaxSize(s, 5000, 7900, i);
testEntriesMaxSize(s, 8000, 12000, i);
testEntriesMaxSize(s, 12000, 15900, i);
testEntriesMaxSize(s, 16000, 21300, i);
testEntriesMaxSize(s, 32000, 42200, i);
testEntriesMaxSize(s, 12000, 17000, i);
testEntriesMaxSize(s, 16000, 23000, i);
testEntriesMaxSize(s, 32000, 46000, i);
s = 64;
testEntriesMaxSize(s, 5000, 7550, i);
testEntriesMaxSize(s, 8000, 11400, i);
testEntriesMaxSize(s, 12000, 16000, i);
testEntriesMaxSize(s, 16000, 22000, i);
testEntriesMaxSize(s, 32000, 43000, i);
testEntriesMaxSize(s, 40000, 54000, i);
testEntriesMaxSize(s, 12000, 18000, i);
testEntriesMaxSize(s, 16000, 24000, i);
testEntriesMaxSize(s, 32000, 47000, i);
testEntriesMaxSize(s, 40000, 60000, i);
s = 128;
testEntriesMaxSize(s, 16000, 23000, i);
testEntriesMaxSize(s, 32000, 44200, i);
testEntriesMaxSize(s, 40000, 56000, i);
testEntriesMaxSize(s, 64000, 92000, i);
testEntriesMaxSize(s, 129000, 190000, i);
testEntriesMaxSize(s, 16000, 24000, i);
testEntriesMaxSize(s, 32000, 50000, i);
testEntriesMaxSize(s, 40000, 62000, i);
testEntriesMaxSize(s, 64000, 98000, i);
testEntriesMaxSize(s, 129000, 204000, i);
s = 256;
testEntriesMaxSize(s, 64000, 92000, i);
testEntriesMaxSize(s, 129000, 192000, i);
testEntriesMaxSize(s, 64000, 100000, i);
testEntriesMaxSize(s, 129000, 213000, i);
}
// hyperbolic average gives more weight to small numbers.
System.out.printf("Score: %.2f%n", scoreCount / score);
@@ -16,11 +16,14 @@
* limitations under the License.
*/
package net.openhft.chronicle.map.utils;
package net.openhft.chronicle.map;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import net.openhft.chronicle.map.Int24Int24MultiMap;
import net.openhft.chronicle.map.IntIntMultiMap;
import net.openhft.chronicle.map.MultiMap;
import net.openhft.lang.collection.SingleThreadedDirectBitSet;
import net.openhft.lang.io.DirectStore;
import org.junit.Assert;
@@ -52,9 +55,9 @@ public class IntIntMultiMapTest {
@Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
{VanillaShortShortMultiMap.class},
{VanillaI24I24MultiMap.class},
{VanillaIntIntMultiMap.class},
{ShortShortMultiMap.class},
{Int24Int24MultiMap.class},
{IntIntMultiMap.class},
});
}