Use memorizing suppliers to considerably improve get() performance of CapabilityCache

This commit is contained in:
DBotThePony 2025-04-05 09:58:50 +07:00
parent 8f9103ca48
commit 43c02b37a8
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -348,6 +348,17 @@ abstract class MatteryBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state
private var cache: BlockCapabilityCache<T, in Direction?>? = null private var cache: BlockCapabilityCache<T, in Direction?>? = null
private val listeners = Listenable.Impl<T?>() private val listeners = Listenable.Impl<T?>()
private val lookupProvider = Supplier<T?> {
if (isRemoved)
return@Supplier null
val get = cache?.capability
provider = Supplier { get }
return@Supplier get
}
private var provider: Supplier<T?> = lookupProvider
override fun addListener(listener: Consumer<T?>): Listenable.L { override fun addListener(listener: Consumer<T?>): Listenable.L {
return listeners.addListener(listener) return listeners.addListener(listener)
} }
@ -358,23 +369,21 @@ abstract class MatteryBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state
} }
override fun get(): T? { override fun get(): T? {
if (isRemoved) return provider.get()
return null
return cache?.capability
} }
val isPresent: Boolean val isPresent: Boolean
get() = cache?.capability != null get() = get() != null
val isEmpty: Boolean val isEmpty: Boolean
get() = cache?.capability == null get() = get() == null
fun rebuildCache() { fun rebuildCache() {
if (!SERVER_IS_LIVE) return if (!SERVER_IS_LIVE) return
val level = level as? ServerLevel val level = level as? ServerLevel
val creationVersion = ++currentVersion val creationVersion = ++currentVersion
provider = lookupProvider
if (level == null) { if (level == null) {
cache = null cache = null
@ -388,12 +397,21 @@ abstract class MatteryBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state
{ !isRemoved || creationVersion != currentVersion }, { !isRemoved || creationVersion != currentVersion },
// IllegalStateException("Do not call getCapability on an invalid cache or from the invalidation listener!") // IllegalStateException("Do not call getCapability on an invalid cache or from the invalidation listener!")
// what a shame. // what a shame.
{ if (SERVER_IS_LIVE) onceServer { if (!isRemoved && creationVersion == currentVersion) listeners.accept(cache?.capability) } }) {
provider = lookupProvider
if (SERVER_IS_LIVE) onceServer { if (!isRemoved && creationVersion == currentVersion) listeners.accept(get()) }
})
onceServer { onceServer {
if (!isRemoved && creationVersion == currentVersion) listeners.accept(cache?.capability) if (!isRemoved && creationVersion == currentVersion) listeners.accept(get())
} }
} }
fun removeCache() {
cache = null
currentVersion++
provider = Supplier { null }
}
} }
val syncher = SynchableGroup() val syncher = SynchableGroup()
@ -424,6 +442,7 @@ abstract class MatteryBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state
override fun setRemoved() { override fun setRemoved() {
super.setRemoved() super.setRemoved()
capabilityCaches.forEach { it.removeCache() }
unsubscribe() unsubscribe()
} }