ability to store PHM<Key,Integer> in more compact format

This commit is contained in:
Maxim.Mossienko
2014-04-10 23:16:42 +02:00
parent 542bb74d27
commit c8e27bf3d3
2 changed files with 40 additions and 6 deletions
@@ -440,14 +440,25 @@ public class PersistentMapTest extends TestCase {
TIntIntHashMap checkMap = new TIntIntHashMap(size);
Random r = new Random(1);
while(size != checkMap.size()) {
checkMap.put(r.nextInt(), size == 0 ? 0 : r.nextInt());
if (checkMap.size() == 0) {
checkMap.put(r.nextInt(), 0);
checkMap.put(r.nextInt(), 0);
checkMap.put(0, r.nextInt());
} else {
checkMap.put(r.nextInt(), r.nextInt());
}
}
long started = System.currentTimeMillis();
PersistentHashMap<Integer, Integer> map = null;
try {
map = new PersistentHashMap<Integer, Integer>(file, EnumeratorIntegerDescriptor.INSTANCE, EnumeratorIntegerDescriptor.INSTANCE);
map = new PersistentHashMap<Integer, Integer>(file, EnumeratorIntegerDescriptor.INSTANCE, EnumeratorIntegerDescriptor.INSTANCE) {
@Override
protected boolean wantCompactIntegralValues() {
return true;
}
};
final PersistentHashMap<Integer, Integer> mapFinal = map;
boolean result = checkMap.forEachEntry(new TIntIntProcedure() {
@@ -467,7 +478,12 @@ public class PersistentMapTest extends TestCase {
map.close();
System.out.println("Done:"+(System.currentTimeMillis() - started));
started = System.currentTimeMillis();
map = new PersistentHashMap<Integer, Integer>(file, EnumeratorIntegerDescriptor.INSTANCE, EnumeratorIntegerDescriptor.INSTANCE);
map = new PersistentHashMap<Integer, Integer>(file, EnumeratorIntegerDescriptor.INSTANCE, EnumeratorIntegerDescriptor.INSTANCE) {
@Override
protected boolean wantCompactIntegralValues() {
return true;
}
};
final PersistentHashMap<Integer, Integer> mapFinal2 = map;
result = checkMap.forEachEntry(new TIntIntProcedure() {
@Override
@@ -62,6 +62,7 @@ public class PersistentHashMap<Key, Value> extends PersistentEnumeratorDelegate<
private final int myParentValueRefOffset;
@NotNull private final byte[] myRecordBuffer;
@NotNull private final byte[] mySmallRecordBuffer;
private final boolean myIntMapping;
private final boolean myCanReEnumerate;
private int myLargeIndexWatermarkId; // starting with this id we store offset in adjacent file in long format
private boolean myIntAddressForNewRecord;
@@ -112,6 +113,8 @@ public class PersistentHashMap<Key, Value> extends PersistentEnumeratorDelegate<
myAppendCache = createAppendCache(keyDescriptor);
final PersistentEnumeratorBase.RecordBufferHandler<PersistentEnumeratorBase> recordHandler = myEnumerator.getRecordHandler();
myParentValueRefOffset = recordHandler.getRecordBuffer(myEnumerator).length;
myIntMapping = valueExternalizer instanceof IntInlineKeyDescriptor && wantCompactIntegralValues();
myRecordBuffer = new byte[myParentValueRefOffset + 8];
mySmallRecordBuffer = new byte[myParentValueRefOffset + 4];
@@ -180,6 +183,10 @@ public class PersistentHashMap<Key, Value> extends PersistentEnumeratorDelegate<
}
}
protected boolean wantCompactIntegralValues() {
return false;
}
private SLRUCache<Key, BufferExposingByteArrayOutputStream> createAppendCache(final KeyDescriptor<Key> keyDescriptor) {
final EqualityPolicy<Key> hashingStrategy = new EqualityPolicy<Key>() {
@Override
@@ -306,14 +313,18 @@ public class PersistentHashMap<Key, Value> extends PersistentEnumeratorDelegate<
myEnumerator.markDirty(true);
myAppendCache.remove(key);
final int id = enumerate(key);
if (myIntMapping) {
myEnumerator.myStorage.putInt(id + myParentValueRefOffset, (Integer)value);
return;
}
final BufferExposingByteArrayOutputStream bytes = new BufferExposingByteArrayOutputStream();
AppendStream appenderStream = ourFlyweightAppenderStream.getValue();
appenderStream.setOut(bytes);
myValueExternalizer.save(appenderStream, value);
appenderStream.setOut(null);
final int id = enumerate(key);
long oldheader = readValueId(id);
if (oldheader != NULL_ADDR) {
myLiveAndGarbageKeysCounter++;
@@ -357,6 +368,7 @@ public class PersistentHashMap<Key, Value> extends PersistentEnumeratorDelegate<
};
protected void doAppendData(Key key, @NotNull ValueDataAppender appender) throws IOException {
assert !myIntMapping;
myEnumerator.markDirty(true);
AppendStream appenderStream = ourFlyweightAppenderStream.getValue();
@@ -413,11 +425,15 @@ public class PersistentHashMap<Key, Value> extends PersistentEnumeratorDelegate<
if (id == PersistentEnumerator.NULL_ID) {
return null;
}
if (myIntMapping) {
return (Value)(Integer)myEnumerator.myStorage.getInt(id + myParentValueRefOffset);
}
final long oldHeader = readValueId(id);
if (oldHeader == PersistentEnumerator.NULL_ID) {
return null;
}
PersistentHashMapValueStorage.ReadResult readResult = myValueStorage.readBytes(oldHeader);
if (readResult.offset != oldHeader) {
myEnumerator.markDirty(true);
@@ -454,6 +470,7 @@ public class PersistentHashMap<Key, Value> extends PersistentEnumeratorDelegate<
if (id == PersistentEnumerator.NULL_ID) {
return false;
}
if(myIntMapping) return true;
return readValueId(id) != NULL_ADDR;
}
finally {
@@ -475,6 +492,7 @@ public class PersistentHashMap<Key, Value> extends PersistentEnumeratorDelegate<
if (id == PersistentEnumerator.NULL_ID) {
return;
}
assert !myIntMapping; // removal isn't supported
myEnumerator.markDirty(true);
final long record = readValueId(id);