Use on-heap elastic bytes in DataAccess implementation in order not to pollute direct memery with small allocations, reallocations and associated Cleaners, when many ChronicleMaps are created in the JVM. Also, NativeBytes reallocation granularity is 4KB, that is too much for likely small keys and values.

This commit is contained in:
leventov
2016-11-05 15:06:44 -06:00
parent b484286b1b
commit 68c29c4c54
7 changed files with 47 additions and 10 deletions
@@ -41,7 +41,7 @@ abstract class AbstractCharSequenceUtf8DataAccess<T extends CharSequence> extend
}
private void initTransients() {
bytes = Bytes.allocateElasticDirect(1);
bytes = DefaultElasticBytes.allocateDefaultElasticBytes();
}
@Override
@@ -47,7 +47,7 @@ public class BytesMarshallableDataAccess<T extends BytesMarshallable>
}
private void initTransients() {
bytes = Bytes.allocateElasticDirect(1);
bytes = DefaultElasticBytes.allocateDefaultElasticBytes();
targetBytes = VanillaBytes.vanillaBytes();
}
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2012, 2016 higherfrequencytrading.com
* Copyright (C) 2016 Roman Leventov
*
* 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.serialization.impl;
import net.openhft.chronicle.bytes.Bytes;
final class DefaultElasticBytes {
public static Bytes<?> allocateDefaultElasticBytes() {
return Bytes.elasticHeapByteBuffer(32);
}
private DefaultElasticBytes() {}
}
@@ -52,7 +52,7 @@ public class ExternalBytesMarshallableDataAccess<T> extends InstanceCreatingMars
}
private void initTransients() {
bytes = Bytes.allocateElasticDirect(1);
bytes = DefaultElasticBytes.allocateDefaultElasticBytes();
}
@Override
@@ -45,7 +45,7 @@ public class SerializableDataAccess<T extends Serializable> extends AbstractData
}
void initTransients() {
bytes = Bytes.allocateElasticDirect(1);
bytes = DefaultElasticBytes.allocateDefaultElasticBytes();
out = bytes.outputStream();
in = bytes.inputStream();
}
@@ -62,7 +62,7 @@ public class SizedMarshallableDataAccess<T> extends InstanceCreatingMarshaller<T
}
private void initTransients() {
bytes = Bytes.allocateElasticDirect(1);
bytes = DefaultElasticBytes.allocateDefaultElasticBytes();
targetBytes = VanillaBytes.vanillaBytes();
}
@@ -17,8 +17,8 @@
package net.openhft.chronicle.hash.serialization.impl;
import net.openhft.chronicle.bytes.Byteable;
import net.openhft.chronicle.bytes.RandomDataInput;
import net.openhft.chronicle.bytes.*;
import net.openhft.chronicle.core.Maths;
import net.openhft.chronicle.hash.AbstractData;
import net.openhft.chronicle.hash.Data;
import net.openhft.chronicle.hash.serialization.DataAccess;
@@ -29,7 +29,7 @@ import net.openhft.chronicle.wire.WireOut;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static net.openhft.chronicle.bytes.NativeBytesStore.nativeStoreWithFixedCapacity;
import java.nio.ByteBuffer;
public class ValueDataAccess<T> extends AbstractData<T> implements DataAccess<T> {
@@ -68,8 +68,16 @@ public class ValueDataAccess<T> extends AbstractData<T> implements DataAccess<T>
nativeInstanceAsCopyable = (Copyable) nativeInstance;
nativeClass = (Class<? extends T>) nativeInstance.getClass();
heapClass = Values.heapClassFor(valueType);
nativeInstance.bytesStore(nativeStoreWithFixedCapacity(nativeInstance.maxSize()),
0, nativeInstance.maxSize());
nativeInstance.bytesStore(allocateBytesStoreForInstance(), 0, nativeInstance.maxSize());
}
private BytesStore allocateBytesStoreForInstance() {
long instanceSize = nativeInstance.maxSize();
if (instanceSize > Bytes.MAX_BYTE_BUFFER_CAPACITY) {
return NativeBytesStore.nativeStoreWithFixedCapacity(instanceSize);
} else {
return BytesStore.wrap(ByteBuffer.allocate(Maths.toUInt31(instanceSize)));
}
}
protected T createInstance() {