Экспериментальный самодельный StringInterner

This commit is contained in:
DBotThePony 2023-03-29 14:40:53 +07:00
parent 22b384b2a5
commit 050dddcca7
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -5,7 +5,9 @@ import com.github.benmanes.caffeine.cache.Caffeine
import com.github.benmanes.caffeine.cache.Interner
import com.google.gson.*
import com.google.gson.internal.bind.JsonTreeReader
import it.unimi.dsi.fastutil.Hash
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
import org.apache.logging.log4j.LogManager
import org.lwjgl.stb.STBImage
@ -70,6 +72,7 @@ import ru.dbotthepony.kstarbound.util.WriteOnce
import ru.dbotthepony.kstarbound.util.traverseJsonPath
import ru.dbotthepony.kvector.vector.nint.Vector2i
import java.io.*
import java.lang.ref.ReferenceQueue
import java.lang.ref.WeakReference
import java.text.DateFormat
import java.time.Duration
@ -805,3 +808,75 @@ class Starbound : ISBFileLocator {
private val polyfill by lazy { loadInternalScript("polyfill") }
}
}
private class StringInterner(private val segmentBits: Int) : Interner<String>, Hash.Strategy<Any> {
class Ref(referent: String, queue: ReferenceQueue<String>) : WeakReference<String>(referent, queue) {
val hash = referent.hashCode()
override fun hashCode(): Int {
return hash
}
}
override fun equals(a: Any?, b: Any?): Boolean {
if (a is String && b is Ref) return a == b.get()
if (a is Ref && b is String) return a.get() == b
return a === b
}
override fun hashCode(o: Any): Int {
return o.hashCode()
}
private val queue = ReferenceQueue<String>()
private val actualSegmentBits: Int
init {
var result = 0
for (i in 0 until segmentBits) {
result = result or (1.shl(i))
}
actualSegmentBits = result
}
private val cleaner = Runnable {
while (true) {
val ref = queue.remove() as Ref
val segment = segments[ref.hash and actualSegmentBits]
synchronized(segment) {
val removed = segment.remove(ref)
check(removed === ref) { "Expected to remove reference $ref from segment ${ref.hash and actualSegmentBits} (full hash: ${ref.hash}), but we removed $removed (removed hash: ${removed.hashCode()}, removed segment: ${removed.hashCode() and actualSegmentBits})" }
}
}
}
private val thread = Thread(cleaner, "String Interner Cleanup Thread")
init {
thread.priority = 2
thread.isDaemon = true
thread.start()
}
private val segments: Array<Object2ObjectOpenCustomHashMap<Any, Any>> = Array(1.shl(segmentBits)) { Object2ObjectOpenCustomHashMap(this) }
override fun intern(sample: String): String {
val hash = sample.hashCode()
val segment = segments[hash and actualSegmentBits]
synchronized(segment) {
val canonical = (segment[sample] as Ref?)?.get()
if (canonical != null) {
return canonical
}
val ref = Ref(sample, queue)
segment.put(ref, ref)
return sample
}
}
}