mirror of
https://github.com/OpenHFT/Chronicle-Map.git
synced 2021-09-13 01:26:12 +00:00
Optimize SizedMarshallableDataAccess to avoid double data copy when writing values
This commit is contained in:
+25
-6
@@ -16,8 +16,7 @@
|
||||
|
||||
package net.openhft.chronicle.hash.serialization.impl;
|
||||
|
||||
import net.openhft.chronicle.bytes.Bytes;
|
||||
import net.openhft.chronicle.bytes.RandomDataInput;
|
||||
import net.openhft.chronicle.bytes.*;
|
||||
import net.openhft.chronicle.hash.Data;
|
||||
import net.openhft.chronicle.hash.serialization.DataAccess;
|
||||
import net.openhft.chronicle.hash.serialization.SizedReader;
|
||||
@@ -36,8 +35,11 @@ public class SizedMarshallableDataAccess<T> extends InstanceCreatingMarshaller<T
|
||||
private SizedReader<T> sizedReader;
|
||||
private SizedWriter<? super T> sizedWriter;
|
||||
|
||||
/** Cache field */
|
||||
// Cache fields
|
||||
private transient boolean bytesInit;
|
||||
private transient Bytes bytes;
|
||||
private transient long size;
|
||||
private transient VanillaBytes targetBytes;
|
||||
|
||||
/** State field */
|
||||
private transient T instance;
|
||||
@@ -60,10 +62,16 @@ public class SizedMarshallableDataAccess<T> extends InstanceCreatingMarshaller<T
|
||||
|
||||
private void initTransients() {
|
||||
bytes = Bytes.allocateElasticDirect(1);
|
||||
targetBytes = VanillaBytes.vanillaBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RandomDataInput bytes() {
|
||||
if (!bytesInit) {
|
||||
bytes.clear();
|
||||
sizedWriter.write(bytes, size, instance);
|
||||
bytesInit = true;
|
||||
}
|
||||
return bytes.bytesStore();
|
||||
}
|
||||
|
||||
@@ -74,7 +82,18 @@ public class SizedMarshallableDataAccess<T> extends InstanceCreatingMarshaller<T
|
||||
|
||||
@Override
|
||||
public long size() {
|
||||
return bytes.readRemaining();
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(RandomDataOutput target, long targetOffset) {
|
||||
if (bytesInit || !(target instanceof BytesStore)) {
|
||||
target.write(targetOffset, bytes(), offset(), size);
|
||||
} else {
|
||||
targetBytes.bytesStore((BytesStore) target, targetOffset, size);
|
||||
sizedWriter.write(targetBytes, size, instance);
|
||||
targetBytes.bytesStore(NoBytesStore.NO_BYTES_STORE, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,8 +128,8 @@ public class SizedMarshallableDataAccess<T> extends InstanceCreatingMarshaller<T
|
||||
@Override
|
||||
public Data<T> getData(@NotNull T instance) {
|
||||
this.instance = instance;
|
||||
bytes.clear();
|
||||
sizedWriter.write(bytes, sizedWriter.size(instance), instance);
|
||||
this.size = sizedWriter.size(instance);
|
||||
bytesInit = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -93,11 +93,13 @@ public abstract class MapEntryStages<K, V> extends HashEntryStages<K>
|
||||
// the off-heap bytes. This condition avoids in-place data copy.
|
||||
// TODO would be nice to reduce scope of this check, i. e. check only when it could be
|
||||
// true, and avoid when it surely false (fresh value put, relocating put etc.)
|
||||
RandomDataInput valueBytes = value.bytes();
|
||||
if (valueBytes instanceof NativeBytesStore &&
|
||||
valueBytes.address(value.offset()) == s.segmentBS.address(valueOffset)) {
|
||||
return;
|
||||
}
|
||||
// TODO this optimization is now disabled, because it calls value.bytes() that forces double
|
||||
// data copy, if sizedReader/Writer configured for the value.
|
||||
// RandomDataInput valueBytes = value.bytes();
|
||||
// if (valueBytes instanceof NativeBytesStore &&
|
||||
// valueBytes.address(value.offset()) == s.segmentBS.address(valueOffset)) {
|
||||
// return;
|
||||
// }
|
||||
value.writeTo(s.segmentBS, valueOffset);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user