Skip to content

Commit 73fb900

Browse files
Add additional example, add README.md under examples/map.
1 parent 211f853 commit 73fb900

File tree

7 files changed

+146
-20
lines changed

7 files changed

+146
-20
lines changed

examples/map/README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# map examples
2+
3+
## OnHeapDemo
4+
5+
* Put 20,000 CacheObject instances into a ConcurrentHashMap.
6+
* Each CacheObject instance contains a random string of length 500KB.
7+
* This is a total of 10 GB of data stored on the normal Java heap.
8+
* This application does not make use of any features of the native_memory_allocator library. It is provided for comparison with NativeMemoryMap demos using off-heap storage.
9+
10+
## OffHeapDemo
11+
12+
* Put 20,000 CacheObject instances into a NativeMemoryMap.
13+
* This demo uses the ConcurrentHashMap backend for NativeMemoryMap, which does not support eviction.
14+
* Each CacheObject instance contains a random string of length 500KB.
15+
* This is a total of 10 GB of data in off-heap memory.
16+
17+
## OffHeapDemoWithEviction
18+
19+
* Same as OffHeapDemo but uses the Caffeine backend with maximumSize of 10,000 entries.
20+
* Expect 10,000 entries at end of run with 10,000 total evictions.

examples/map/src/main/kotlin/com/target/nativememoryallocator/examples/map/OffHeapDemo.kt

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package com.target.nativememoryallocator.examples.map
22

33
import com.target.nativememoryallocator.allocator.NativeMemoryAllocatorBuilder
4-
import com.target.nativememoryallocator.buffer.OnHeapMemoryBuffer
4+
import com.target.nativememoryallocator.examples.map.utils.CacheObject
5+
import com.target.nativememoryallocator.examples.map.utils.CacheObjectSerializer
6+
import com.target.nativememoryallocator.examples.map.utils.buildRandomString
57
import com.target.nativememoryallocator.map.NativeMemoryMapBackend
68
import com.target.nativememoryallocator.map.NativeMemoryMapBuilder
7-
import com.target.nativememoryallocator.map.NativeMemoryMapSerializer
89
import kotlinx.coroutines.*
910
import mu.KotlinLogging
1011
import kotlin.random.Random
@@ -15,9 +16,11 @@ private val logger = KotlinLogging.logger {}
1516
/**
1617
* Demo application that puts 20,000 [CacheObject] instances into a [NativeMemoryMap].
1718
*
19+
* This demo uses the ConcurrentHashMap backend for [NativeMemoryMap].
20+
*
1821
* Each [CacheObject] instances contains a random string of length 500KB.
1922
*
20-
* This is a total of 10 GB of data.
23+
* This is a total of 10 GB of data in off-heap memory.
2124
*
2225
* [OnHeapDemo] is the same application using normal on-heap storage for comparison.
2326
*/
@@ -83,20 +86,6 @@ class OffHeapDemo {
8386

8487
}
8588

86-
private class CacheObjectSerializer : NativeMemoryMapSerializer<CacheObject> {
87-
88-
override fun deserializeFromOnHeapMemoryBuffer(onHeapMemoryBuffer: OnHeapMemoryBuffer): CacheObject {
89-
return CacheObject(
90-
s = String(onHeapMemoryBuffer.toTrimmedArray()),
91-
)
92-
}
93-
94-
override fun serializeToByteArray(value: CacheObject): ByteArray {
95-
return value.s.toByteArray()
96-
}
97-
98-
}
99-
10089
suspend fun main() {
10190
withContext(Dispatchers.Default) {
10291
OffHeapDemo().run()
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package com.target.nativememoryallocator.examples.map
2+
3+
import com.target.nativememoryallocator.allocator.NativeMemoryAllocatorBuilder
4+
import com.target.nativememoryallocator.examples.map.utils.CacheObject
5+
import com.target.nativememoryallocator.examples.map.utils.CacheObjectSerializer
6+
import com.target.nativememoryallocator.examples.map.utils.buildRandomString
7+
import com.target.nativememoryallocator.map.NativeMemoryMapBackend
8+
import com.target.nativememoryallocator.map.NativeMemoryMapBuilder
9+
import kotlinx.coroutines.*
10+
import mu.KotlinLogging
11+
import kotlin.random.Random
12+
13+
private val logger = KotlinLogging.logger {}
14+
15+
16+
/**
17+
* Same as [OffHeapDemo] but uses the Caffeine backend with maximumSize of 10,000 entries.
18+
*/
19+
class OffHeapDemoWithEviction {
20+
21+
private val numEntries = 20_000
22+
23+
private val randomIndex = Random.nextInt(0, numEntries)
24+
25+
private val nativeMemoryAllocator = NativeMemoryAllocatorBuilder(
26+
pageSizeBytes = 4_096, // 4 KB
27+
nativeMemorySizeBytes = (20L * 1_024L * 1_024L * 1_024L), // 20 GB
28+
).build()
29+
30+
private val nativeMemoryMap = NativeMemoryMapBuilder<Int, CacheObject>(
31+
valueSerializer = CacheObjectSerializer(),
32+
nativeMemoryAllocator = nativeMemoryAllocator,
33+
backend = NativeMemoryMapBackend.CAFFEINE,
34+
caffeineConfigFunction = { caffeineConfigBuilder ->
35+
caffeineConfigBuilder
36+
.maximumSize(10_000)
37+
.recordStats()
38+
}
39+
).build()
40+
41+
private fun putValueIntoMap(i: Int) {
42+
if ((i % 100) == 0) {
43+
logger.info { "put i = $i" }
44+
}
45+
val value = buildRandomString(length = 500 * 1_024)
46+
if (i == randomIndex) {
47+
logger.info { "put randomIndex = $randomIndex value.length = ${value.length}" }
48+
logger.info { "value.substring(0,20) = ${value.substring(0, 20)}" }
49+
}
50+
nativeMemoryMap.put(
51+
key = i,
52+
value = CacheObject(
53+
s = value,
54+
),
55+
)
56+
}
57+
58+
suspend fun run() {
59+
logger.info { "begin run randomIndex = $randomIndex" }
60+
61+
coroutineScope {
62+
(0 until numEntries).forEach { i ->
63+
launch {
64+
putValueIntoMap(i = i)
65+
}
66+
}
67+
}
68+
69+
logger.info { "nativeMemoryMap.size = ${nativeMemoryMap.size}" }
70+
logger.info { "nativeMemoryAllocator.nativeMemoryAllocatorMetadata = ${nativeMemoryAllocator.nativeMemoryAllocatorMetadata}" }
71+
72+
val randomIndexValue = nativeMemoryMap.get(key = randomIndex)
73+
randomIndexValue?.let {
74+
logger.info { "get randomIndex = $randomIndex" }
75+
logger.info { "randomIndexValue.s.length = ${it.s.length}" }
76+
logger.info { "randomIndexValue.s.substring(0,20) = ${it.s.substring(0, 20)}" }
77+
}
78+
79+
logger.info { "caffeine eviction count = ${nativeMemoryMap.stats.caffeineStats?.evictionCount()}" }
80+
81+
while (true) {
82+
delay(1_000)
83+
}
84+
}
85+
86+
}
87+
88+
suspend fun main() {
89+
withContext(Dispatchers.Default) {
90+
OffHeapDemoWithEviction().run()
91+
}
92+
}

examples/map/src/main/kotlin/com/target/nativememoryallocator/examples/map/OnHeapDemo.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.target.nativememoryallocator.examples.map
22

3+
import com.target.nativememoryallocator.examples.map.utils.CacheObject
4+
import com.target.nativememoryallocator.examples.map.utils.buildRandomString
35
import kotlinx.coroutines.*
46
import mu.KotlinLogging
57
import java.util.concurrent.ConcurrentHashMap
@@ -10,7 +12,7 @@ private val logger = KotlinLogging.logger {}
1012
/**
1113
* Demo application that puts 20,000 [CacheObject] instances into a [ConcurrentHashMap].
1214
*
13-
* Each [CacheObject] instances contains a random string of length 500KB.
15+
* Each [CacheObject] instance contains a random string of length 500KB.
1416
*
1517
* This is a total of 10 GB of data stored on the normal Java heap.
1618
*

examples/map/src/main/kotlin/com/target/nativememoryallocator/examples/map/CacheObject.kt renamed to examples/map/src/main/kotlin/com/target/nativememoryallocator/examples/map/utils/CacheObject.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.target.nativememoryallocator.examples.map
1+
package com.target.nativememoryallocator.examples.map.utils
22

33
/**
44
* A demo cache object containing a single field [s] of type [String].
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.target.nativememoryallocator.examples.map.utils
2+
3+
import com.target.nativememoryallocator.buffer.OnHeapMemoryBuffer
4+
import com.target.nativememoryallocator.map.NativeMemoryMapSerializer
5+
6+
/**
7+
* A [NativeMemoryMapSerializer] for [CacheObject].
8+
*
9+
* Used when storing [CacheObject] in a [NativeMemoryMap].
10+
*/
11+
class CacheObjectSerializer : NativeMemoryMapSerializer<CacheObject> {
12+
13+
override fun deserializeFromOnHeapMemoryBuffer(onHeapMemoryBuffer: OnHeapMemoryBuffer): CacheObject {
14+
return CacheObject(
15+
s = String(onHeapMemoryBuffer.toTrimmedArray()),
16+
)
17+
}
18+
19+
override fun serializeToByteArray(value: CacheObject): ByteArray {
20+
return value.s.toByteArray()
21+
}
22+
23+
}

examples/map/src/main/kotlin/com/target/nativememoryallocator/examples/map/StringUtils.kt renamed to examples/map/src/main/kotlin/com/target/nativememoryallocator/examples/map/utils/StringUtils.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.target.nativememoryallocator.examples.map
1+
package com.target.nativememoryallocator.examples.map.utils
22

33
private val charset = ('a'..'z') + ('A'..'Z') + ('0'..'9')
44

0 commit comments

Comments
 (0)