From b38f7c52a4e7e4d2ea2656cf6ef13d0034772e68 Mon Sep 17 00:00:00 2001 From: Aaron Riekenberg Date: Mon, 6 Feb 2023 11:53:01 -0600 Subject: [PATCH 1/3] Avoid byte array copy for reads in NMA valueSerializer. --- .../benchmarks/OffHeapGetPutBenchmark.kt | 13 ++++++------ .../benchmarks/impl/NMAOffHeapCache.kt | 21 ++++++++++--------- .../benchmarks/impl/RocksDBOffHeapCache.kt | 11 +++++----- .../impl/UnimplementedOffHeapCache.kt | 7 ++++--- 4 files changed, 28 insertions(+), 24 deletions(-) diff --git a/benchmarks/src/jmh/kotlin/com/target/nativememoryallocator/benchmarks/OffHeapGetPutBenchmark.kt b/benchmarks/src/jmh/kotlin/com/target/nativememoryallocator/benchmarks/OffHeapGetPutBenchmark.kt index 3b6255e..92b1633 100644 --- a/benchmarks/src/jmh/kotlin/com/target/nativememoryallocator/benchmarks/OffHeapGetPutBenchmark.kt +++ b/benchmarks/src/jmh/kotlin/com/target/nativememoryallocator/benchmarks/OffHeapGetPutBenchmark.kt @@ -5,6 +5,7 @@ import com.target.nativememoryallocator.benchmarks.impl.RocksDBOffHeapCache import com.target.nativememoryallocator.benchmarks.impl.UnimplementedOffHeapCache import mu.KotlinLogging import org.openjdk.jmh.annotations.* +import java.nio.ByteBuffer private val logger = KotlinLogging.logger {} @@ -26,7 +27,7 @@ open class OffHeapGetPutBenchmark { ) var cacheType: String = "" - private var cache: OffHeapCache = UnimplementedOffHeapCache + private var cache: OffHeapCache = UnimplementedOffHeapCache @State(Scope.Thread) open class ThreadState { @@ -60,7 +61,7 @@ open class OffHeapGetPutBenchmark { } for (i in 0 until NUM_ENTRIES) { - cache.put(key = i.toString(), value = ByteArray(VALUE_SIZE)) + cache.put(key = i.toString(), value = ByteBuffer.wrap(ByteArray(VALUE_SIZE))) } cache.logMetadata() @@ -78,7 +79,7 @@ open class OffHeapGetPutBenchmark { @Benchmark @Group("read_only") @GroupThreads(8) - fun readOnly(threadState: ThreadState): ByteArray? { + fun readOnly(threadState: ThreadState): ByteBuffer? { val key = threadState.nextIndex().toString() val value = cache.get(key = key) if (value == null) { @@ -92,13 +93,13 @@ open class OffHeapGetPutBenchmark { @GroupThreads(8) fun writeOnly(threadState: ThreadState) { val key = threadState.nextIndex().toString() - cache.put(key = key, value = ByteArray(VALUE_SIZE)) + cache.put(key = key, value = ByteBuffer.wrap(ByteArray(VALUE_SIZE))) } @Benchmark @Group("readwrite") @GroupThreads(6) - fun readwrite_get(threadState: ThreadState): ByteArray? { + fun readwrite_get(threadState: ThreadState): ByteBuffer? { val key = threadState.nextIndex().toString() val value = cache.get(key = key) if (value == null) { @@ -112,7 +113,7 @@ open class OffHeapGetPutBenchmark { @GroupThreads(2) fun readwrite_put(threadState: ThreadState) { val key = threadState.nextIndex().toString() - cache.put(key = key, value = ByteArray(VALUE_SIZE)) + cache.put(key = key, value = ByteBuffer.wrap(ByteArray(VALUE_SIZE))) } } \ No newline at end of file diff --git a/benchmarks/src/jmh/kotlin/com/target/nativememoryallocator/benchmarks/impl/NMAOffHeapCache.kt b/benchmarks/src/jmh/kotlin/com/target/nativememoryallocator/benchmarks/impl/NMAOffHeapCache.kt index 5c1d4e6..3f138a9 100644 --- a/benchmarks/src/jmh/kotlin/com/target/nativememoryallocator/benchmarks/impl/NMAOffHeapCache.kt +++ b/benchmarks/src/jmh/kotlin/com/target/nativememoryallocator/benchmarks/impl/NMAOffHeapCache.kt @@ -7,6 +7,7 @@ import com.target.nativememoryallocator.map.NativeMemoryMapBackend import com.target.nativememoryallocator.map.NativeMemoryMapBuilder import com.target.nativememoryallocator.map.NativeMemoryMapSerializer import mu.KotlinLogging +import java.nio.ByteBuffer private val logger = KotlinLogging.logger {} @@ -14,10 +15,10 @@ private val logger = KotlinLogging.logger {} /** * NMA implementation of OffHeapCache. */ -class NMAOffHeapCache : OffHeapCache { +class NMAOffHeapCache : OffHeapCache { init { - logger.info { "initializing NMAOffHeapCache" } + logger.info { "initializing NMAOffHeapCache with asByteBuffer change" } } private val nativeMemoryAllocator = NativeMemoryAllocatorBuilder( @@ -25,27 +26,27 @@ class NMAOffHeapCache : OffHeapCache { nativeMemorySizeBytes = (10L * 1024 * 1024 * 1024), //10gb, ).build() - private val valueSerializer = object : NativeMemoryMapSerializer { - override fun deserializeFromOnHeapMemoryBuffer(onHeapMemoryBuffer: OnHeapMemoryBuffer): ByteArray { - return onHeapMemoryBuffer.toTrimmedArray() + private val valueSerializer = object : NativeMemoryMapSerializer { + override fun deserializeFromOnHeapMemoryBuffer(onHeapMemoryBuffer: OnHeapMemoryBuffer): ByteBuffer { + return onHeapMemoryBuffer.asByteBuffer() } - override fun serializeToByteArray(value: ByteArray): ByteArray { - return value + override fun serializeToByteArray(value: ByteBuffer): ByteArray { + return value.array() } }; - private val nativeMemoryMap = NativeMemoryMapBuilder( + private val nativeMemoryMap = NativeMemoryMapBuilder( valueSerializer = valueSerializer, nativeMemoryAllocator = nativeMemoryAllocator, backend = NativeMemoryMapBackend.CAFFEINE, ).build() - override fun get(key: String): ByteArray? { + override fun get(key: String): ByteBuffer? { return nativeMemoryMap.get(key = key) } - override fun put(key: String, value: ByteArray) { + override fun put(key: String, value: ByteBuffer) { nativeMemoryMap.put(key = key, value = value) } diff --git a/benchmarks/src/jmh/kotlin/com/target/nativememoryallocator/benchmarks/impl/RocksDBOffHeapCache.kt b/benchmarks/src/jmh/kotlin/com/target/nativememoryallocator/benchmarks/impl/RocksDBOffHeapCache.kt index ec3b5fc..661971d 100644 --- a/benchmarks/src/jmh/kotlin/com/target/nativememoryallocator/benchmarks/impl/RocksDBOffHeapCache.kt +++ b/benchmarks/src/jmh/kotlin/com/target/nativememoryallocator/benchmarks/impl/RocksDBOffHeapCache.kt @@ -4,13 +4,14 @@ import com.target.nativememoryallocator.benchmarks.OffHeapCache import mu.KotlinLogging import org.rocksdb.RocksDB import java.io.File +import java.nio.ByteBuffer private val logger = KotlinLogging.logger {} /** * RocksDB implementation of OffHeapCache. */ -class RocksDBOffHeapCache : OffHeapCache { +class RocksDBOffHeapCache : OffHeapCache { private val rocksDbDir: String @@ -28,12 +29,12 @@ class RocksDBOffHeapCache : OffHeapCache { rocksDB = RocksDB.open(rocksDbDir) } - override fun get(key: String): ByteArray? { - return rocksDB.get(key.toByteArray()) + override fun get(key: String): ByteBuffer? { + return rocksDB.get(key.toByteArray())?.let { ByteBuffer.wrap(it) } } - override fun put(key: String, value: ByteArray) { - rocksDB.put(key.toByteArray(), value) + override fun put(key: String, value: ByteBuffer) { + rocksDB.put(key.toByteArray(), value.array()) } override fun size(): Int { diff --git a/benchmarks/src/jmh/kotlin/com/target/nativememoryallocator/benchmarks/impl/UnimplementedOffHeapCache.kt b/benchmarks/src/jmh/kotlin/com/target/nativememoryallocator/benchmarks/impl/UnimplementedOffHeapCache.kt index 4c2a04f..bfd91d6 100644 --- a/benchmarks/src/jmh/kotlin/com/target/nativememoryallocator/benchmarks/impl/UnimplementedOffHeapCache.kt +++ b/benchmarks/src/jmh/kotlin/com/target/nativememoryallocator/benchmarks/impl/UnimplementedOffHeapCache.kt @@ -1,18 +1,19 @@ package com.target.nativememoryallocator.benchmarks.impl import com.target.nativememoryallocator.benchmarks.OffHeapCache +import java.nio.ByteBuffer /** * Unimplemented OffHeapCache. * All methods throw NotImplementedError. */ -object UnimplementedOffHeapCache : OffHeapCache { +object UnimplementedOffHeapCache : OffHeapCache { - override fun get(key: String): ByteArray? { + override fun get(key: String): ByteBuffer? { throw NotImplementedError() } - override fun put(key: String, value: ByteArray) { + override fun put(key: String, value: ByteBuffer) { throw NotImplementedError() } From 9860fb85d9486c7445b82914331765d925d1dcab Mon Sep 17 00:00:00 2001 From: Aaron Riekenberg Date: Tue, 7 Feb 2023 13:38:49 -0600 Subject: [PATCH 2/3] Update jmh options. --- benchmarks/build.gradle.kts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/benchmarks/build.gradle.kts b/benchmarks/build.gradle.kts index 3b718d6..b1bacf7 100644 --- a/benchmarks/build.gradle.kts +++ b/benchmarks/build.gradle.kts @@ -16,10 +16,10 @@ dependencies { } jmh { - warmupIterations.set(3) - iterations.set(3) + warmupIterations.set(5) + iterations.set(5) fork.set(1) forceGC.set(true) failOnError.set(true) - jvmArgs.set(listOf("-Xmx2G")) + jvmArgs.set(listOf("-Xmx4G")) } \ No newline at end of file From f50fa09f94c71dff932fe01732e0431c2bae631a Mon Sep 17 00:00:00 2001 From: Aaron Riekenberg Date: Tue, 7 Feb 2023 13:52:32 -0600 Subject: [PATCH 3/3] Update log. --- .../nativememoryallocator/benchmarks/impl/NMAOffHeapCache.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmarks/src/jmh/kotlin/com/target/nativememoryallocator/benchmarks/impl/NMAOffHeapCache.kt b/benchmarks/src/jmh/kotlin/com/target/nativememoryallocator/benchmarks/impl/NMAOffHeapCache.kt index 3f138a9..1221dca 100644 --- a/benchmarks/src/jmh/kotlin/com/target/nativememoryallocator/benchmarks/impl/NMAOffHeapCache.kt +++ b/benchmarks/src/jmh/kotlin/com/target/nativememoryallocator/benchmarks/impl/NMAOffHeapCache.kt @@ -18,7 +18,7 @@ private val logger = KotlinLogging.logger {} class NMAOffHeapCache : OffHeapCache { init { - logger.info { "initializing NMAOffHeapCache with asByteBuffer change" } + logger.info { "initializing NMAOffHeapCache" } } private val nativeMemoryAllocator = NativeMemoryAllocatorBuilder(