1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
package moe.nea.caelo.optifine
import moe.nea.caelo.CaeloCommand
import moe.nea.caelo.config.CConfig
import moe.nea.caelo.event.NeaTickEvent
import moe.nea.caelo.event.ResourceReloadEvent
import moe.nea.caelo.optifine.OptifineRegexCache.cache
import moe.nea.caelo.util.Histogram
import moe.nea.caelo.util.MC
import net.minecraft.item.ItemStack
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import net.optifine.CustomItemProperties
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable
import java.lang.ref.ReferenceQueue
import java.lang.ref.WeakReference
object OptifineCustomItemCache {
init {
CaeloCommand.subcommand("opticache") { args ->
val cache = cacheSizeHistory.lastOrNull() ?: CacheStats()
MC.display("OptiCache stats:")
MC.display("- History: §3${cacheSizeHistory.size}")
MC.display("- Misses: §c${cache.cacheMisses}")
MC.display("- Hits: §a${cache.cacheHits}")
MC.display("- Insertions: §b${cache.insertions}")
MC.display("- Evictions: §b${cache.removals}")
MC.display("- Cache Size: §b${cache.size}")
OptifineRegexCache.printStats()
}
}
val referenceQueue = ReferenceQueue<ItemStack>()
class CacheKeyReference(val cacheKey: CacheKey, itemStack: ItemStack) :
WeakReference<ItemStack>(itemStack, referenceQueue)
class CacheKey(itemStack: ItemStack, val type: Int) {
val hashCode = System.identityHashCode(itemStack) * 31 + type
val ref = CacheKeyReference(this, itemStack)
override fun equals(other: Any?): Boolean {
if (other === this) return true
if (other !is CacheKey) return false
return ref.get() === other.ref.get() && type == other.type
}
override fun hashCode(): Int {
return hashCode
}
fun isPresent(): Boolean {
return ref.get() != null
}
}
data class CacheStats(
var cacheHits: Int = 0,
var cacheMisses: Int = 0,
var insertions: Int = 0,
var size: Int = 0,
var removals: Int = 0,
)
private var map = mutableMapOf<CacheKey, CustomItemProperties?>()
private val cacheSizeHistory = Histogram<CacheStats>(1000)
private var cacheStats = CacheStats()
@SubscribeEvent
fun onResourcePackReload(resourceReload: ResourceReloadEvent) {
map.clear()
}
@SubscribeEvent
fun onTick(event: NeaTickEvent) {
var removeCount = 0
while (true) {
val ref = referenceQueue.poll() as CacheKeyReference? ?: break
removeCount++
map.remove(ref.cacheKey)
}
cacheStats.size = map.size
cacheStats.removals = removeCount
cacheSizeHistory.append(cacheStats)
cacheStats = CacheStats()
}
@JvmStatic
fun retrieveCacheHit(
itemStack: ItemStack,
type: Int,
cir: CallbackInfoReturnable<CustomItemProperties?>
) {
if (!CConfig.config.optiCache.citCache)
return
val key = CacheKey(itemStack, type)
if (!map.containsKey(key)) {
cacheStats.cacheMisses++
return
}
cacheStats.cacheHits++
cir.returnValue = map[key]
}
@JvmStatic
fun storeCustomItemProperties(itemStack: ItemStack, type: Int, cip: CustomItemProperties) {
map[CacheKey(itemStack, type)] = cip
cacheStats.insertions++
}
@JvmStatic
fun storeNoCustomItemProperties(itemStack: ItemStack, type: Int) {
map[CacheKey(itemStack, type)] = null
cacheStats.insertions++
}
}
|