From 2ad524b095632a58db013ab2603c05b8500a8bbc Mon Sep 17 00:00:00 2001 From: "Kenneth J. Shackleton" Date: Sat, 22 Jun 2024 16:36:26 +0100 Subject: [PATCH] Try nullable. --- .../cache/benchmarks/StampedCacheBenchmark.kt | 51 +++++++++++++++++++ .../bloomberg/selekt/cache/CommonLruCache.kt | 48 +++++++++-------- .../selekt/cache/CommonLruCacheTest.kt | 7 ++- 3 files changed, 83 insertions(+), 23 deletions(-) create mode 100644 selekt-java/src/jmh/kotlin/com/bloomberg/selekt/cache/benchmarks/StampedCacheBenchmark.kt diff --git a/selekt-java/src/jmh/kotlin/com/bloomberg/selekt/cache/benchmarks/StampedCacheBenchmark.kt b/selekt-java/src/jmh/kotlin/com/bloomberg/selekt/cache/benchmarks/StampedCacheBenchmark.kt new file mode 100644 index 0000000000..91d5176ebe --- /dev/null +++ b/selekt-java/src/jmh/kotlin/com/bloomberg/selekt/cache/benchmarks/StampedCacheBenchmark.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2024 Bloomberg Finance L.P. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.bloomberg.selekt.cache.benchmarks + +import com.bloomberg.selekt.cache.StampedCache +import org.openjdk.jmh.annotations.Benchmark +import org.openjdk.jmh.annotations.BenchmarkMode +import org.openjdk.jmh.annotations.Level +import org.openjdk.jmh.annotations.Mode +import org.openjdk.jmh.annotations.Scope +import org.openjdk.jmh.annotations.Setup +import org.openjdk.jmh.annotations.State + +@State(Scope.Thread) +open class StampedCacheInput { + internal lateinit var cache: StampedCache + + @Setup(Level.Iteration) + fun setUp() { + cache = StampedCache(1) {} + } +} + +open class StampedCacheBenchmark { + @Benchmark + @BenchmarkMode(Mode.Throughput) + fun getEntry(input: StampedCacheInput) = input.cache.run { + get("1") {} + } + + @Benchmark + @BenchmarkMode(Mode.Throughput) + fun getEntryWithEviction(input: StampedCacheInput) = input.cache.run { + get("1") {} + get("2") {} + } +} diff --git a/selekt-java/src/main/kotlin/com/bloomberg/selekt/cache/CommonLruCache.kt b/selekt-java/src/main/kotlin/com/bloomberg/selekt/cache/CommonLruCache.kt index 01542a5656..4b64769e0b 100644 --- a/selekt-java/src/main/kotlin/com/bloomberg/selekt/cache/CommonLruCache.kt +++ b/selekt-java/src/main/kotlin/com/bloomberg/selekt/cache/CommonLruCache.kt @@ -18,32 +18,36 @@ package com.bloomberg.selekt.cache class CommonLruCache( @PublishedApi + @JvmField internal val maxSize: Int, disposal: (T) -> Unit ) { @PublishedApi - internal var cache: Any = StampedCache(maxSize, disposal) + @JvmField + internal var cache: StampedCache? = StampedCache(maxSize, disposal) + @PublishedApi + @JvmField + internal var linkedCache: LinkedLruCache? = null fun evict(key: String) { - when (val cache = cache) { - is StampedCache<*> -> cache.evict(key) - is LinkedLruCache<*> -> cache.evict(key) - else -> error("Unrecognized cache class: {}") + cache?.let { + it.evict(key) + return } + linkedCache!!.evict(key) } fun evictAll() { - when (val cache = cache) { - is StampedCache<*> -> cache.evictAll() - is LinkedLruCache<*> -> cache.evictAll() - else -> error("Unrecognized cache class: {}") + cache?.let { + it.evictAll() + return } + linkedCache!!.evictAll() } - @Suppress("UNCHECKED_CAST") - inline fun get(key: String, supplier: () -> T): T = when (cache) { - is StampedCache<*> -> (cache as StampedCache).let { - it.get(key) { + inline fun get(key: String, supplier: () -> T): T { + cache?.let { + return it.get(key) { supplier().also { value -> if (it.shouldTransform()) { // Adding another entry to the cache will necessitate the removal of the @@ -51,19 +55,19 @@ class CommonLruCache( // For the implementation of the store currently assigned, this is an O(N) // operation. We transform to an O(1) implementation. transform() - (this@CommonLruCache.cache as LinkedLruCache).store.put(key, value) + linkedCache!!.store.put(key, value) } } } } - is LinkedLruCache<*> -> (cache as LinkedLruCache).get(key, supplier) - else -> error("Unrecognized cache class: {}") + return linkedCache!!.get(key, supplier) } - fun containsKey(key: String) = when (val cache = cache) { - is StampedCache<*> -> cache.containsKey(key) - is LinkedLruCache<*> -> cache.containsKey(key) - else -> error("Unrecognized cache class: {}") + fun containsKey(key: String): Boolean { + cache?.let { + return it.containsKey(key) + } + return linkedCache!!.containsKey(key) } @PublishedApi @@ -71,8 +75,8 @@ class CommonLruCache( @PublishedApi internal fun transform() { - (cache as StampedCache<*>).asLruCache().also { - cache = it + linkedCache = cache!!.asLruCache().also { + cache = null } } } diff --git a/selekt-java/src/test/kotlin/com/bloomberg/selekt/cache/CommonLruCacheTest.kt b/selekt-java/src/test/kotlin/com/bloomberg/selekt/cache/CommonLruCacheTest.kt index 48b2edc80b..c4792c1eb9 100644 --- a/selekt-java/src/test/kotlin/com/bloomberg/selekt/cache/CommonLruCacheTest.kt +++ b/selekt-java/src/test/kotlin/com/bloomberg/selekt/cache/CommonLruCacheTest.kt @@ -16,6 +16,7 @@ package com.bloomberg.selekt.cache +import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows import org.mockito.kotlin.anyOrNull @@ -28,6 +29,7 @@ import org.mockito.kotlin.times import org.mockito.kotlin.verify import org.mockito.kotlin.whenever import kotlin.test.assertFalse +import kotlin.test.assertNotNull import kotlin.test.assertSame import kotlin.test.assertTrue import kotlin.test.fail @@ -44,6 +46,7 @@ internal class CommonLruCacheTest { val cache = CommonLruCache(1, disposal) cache.get("1") { first } assertSame(first, cache.get("1") { fail() }) + assertNotNull(cache.cache) } @Test @@ -53,6 +56,7 @@ internal class CommonLruCacheTest { cache.get("2") { second } assertSame(first, cache.get("1") { fail() }) assertSame(second, cache.get("2") { fail() }) + assertNotNull(cache.cache) } @Test @@ -62,6 +66,7 @@ internal class CommonLruCacheTest { cache.get("2") { second } assertFalse(cache.containsKey("1")) assertSame(second, cache.get("2") { fail() }) + assertNull(cache.cache) } @Test @@ -83,8 +88,8 @@ internal class CommonLruCacheTest { cache.get("2") { second } cache.evictAll() inOrder(disposal) { - verify(disposal, times(1)).invoke(same(first)) verify(disposal, times(1)).invoke(same(second)) + verify(disposal, times(1)).invoke(same(first)) } }