Skip to content

Commit

Permalink
chore: Consistently use T.(T) for supporting both shorthand and objec…
Browse files Browse the repository at this point in the history
…t queries

perf: Avoid going through delegate entirely in shorthand queries
  • Loading branch information
0ffz committed May 31, 2024
1 parent 2f77116 commit 578d72e
Show file tree
Hide file tree
Showing 13 changed files with 112 additions and 105 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.mineinabyss.geary.serialization.formats

import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.SerializationStrategy
import kotlinx.serialization.*
import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.polymorphic
import kotlinx.serialization.modules.subclass
import okio.Path

interface Format {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.mineinabyss.geary.modules.TestEngineModule
import com.mineinabyss.geary.modules.geary
import com.mineinabyss.geary.systems.query.Query
import com.mineinabyss.geary.systems.builders.system
import com.mineinabyss.geary.systems.query.query
import org.openjdk.jmh.annotations.Benchmark
import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.Setup
Expand All @@ -21,16 +22,15 @@ class VelocitySystemBenchmark {
val velocity by get<Velocity>()
var position by get<Position>()
}).exec {
it.position.x += it.velocity.x
it.position.y += it.velocity.y
}
fun createVelocitySystemNoDelegates() = geary.system(
query<Velocity, Position>()
).exec { (velocity, position) ->
position.x += velocity.x
position.y += velocity.y
}
fun createVelocitySystemNoDelegates() = geary.system(object : Query() {
val velocity = get<Velocity>()
var position = get<Position>()
}).exec {
position().x += velocity().x
position().y += velocity().y
}

val velocities = Array(tenMil) { Velocity(it.toFloat() / oneMil, it.toFloat() / oneMil) }
val positions = Array(tenMil) { Position(0f, 0f) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,29 @@ package com.mineinabyss.geary.systems.accessors
import com.mineinabyss.geary.systems.query.Query
import kotlin.properties.ReadOnlyProperty
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty

interface Accessor {
val originalAccessor: Accessor?
}

interface ReadOnlyAccessor<out T> : Accessor, ReadOnlyProperty<Query, T>
interface ReadOnlyAccessor<out T> : Accessor, ReadOnlyProperty<Query, T> {
fun get(query: Query): T

interface ReadWriteAccessor<T> : ReadOnlyAccessor<T>, ReadWriteProperty<Query, T>

override fun getValue(thisRef: Query, property: KProperty<*>): T {
return get(thisRef)
}
}

interface ReadWriteAccessor<T> : ReadOnlyAccessor<T>, ReadWriteProperty<Query, T> {
fun set(query: Query, value: T)

override fun getValue(thisRef: Query, property: KProperty<*>): T {
return get(thisRef)
}

override fun setValue(thisRef: Query, property: KProperty<*>, value: T) {
return set(thisRef, value)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,11 @@ class ComponentAccessor<T : Any>(
if (cachedIndex != -1) cachedDataArray = archetype.componentData[cachedIndex] as MutableObjectList<T>
}

fun get(query: Query): T {
override fun get(query: Query): T {
return cachedDataArray[query.row]
}

fun set(query: Query, value: T) {
override fun set(query: Query, value: T) {
cachedDataArray[query.row] = value
}

override fun getValue(thisRef: Query, property: KProperty<*>): T {
return get(thisRef)
}

override fun setValue(thisRef: Query, property: KProperty<*>, value: T) {
return set(thisRef, value)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ class ComponentOrDefaultAccessor<T>(
private var cachedArchetype: Archetype? = null

@OptIn(UnsafeAccessors::class)
override fun getValue(thisRef: Query, property: KProperty<*>): T {
val archetype = thisRef.archetype
override fun get(query: Query): T {
val archetype = query.archetype
if (archetype !== cachedArchetype) {
cachedArchetype = archetype
cachedIndex = archetype.indexOf(id)
}
if (cachedIndex == -1) return default()
@Suppress("UNCHECKED_CAST")
return archetype.componentData[cachedIndex][thisRef.row] as T
return archetype.componentData[cachedIndex][query.row] as T
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@ package com.mineinabyss.geary.systems.accessors.type

import com.mineinabyss.geary.systems.accessors.ReadOnlyAccessor
import com.mineinabyss.geary.systems.query.Query
import kotlin.reflect.KProperty

class MappedAccessor<T, U>(
override val originalAccessor: ReadOnlyAccessor<T>,
val mapping: (T) -> U,
) : ReadOnlyAccessor<U> {
override fun getValue(thisRef: Query, property: KProperty<*>): U {
val value = originalAccessor.getValue(thisRef, property)
override fun get(query: Query): U {
val value = originalAccessor.get(query)
return mapping(value)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import com.mineinabyss.geary.systems.accessors.Accessor
import com.mineinabyss.geary.systems.accessors.FamilyMatching
import com.mineinabyss.geary.systems.accessors.ReadOnlyAccessor
import com.mineinabyss.geary.systems.query.Query
import kotlin.reflect.KProperty

class RelationsAccessor(
override val originalAccessor: Accessor?,
Expand All @@ -23,8 +22,8 @@ class RelationsAccessor(
private var cachedArchetype: Archetype? = null

@OptIn(UnsafeAccessors::class)
override fun getValue(thisRef: Query, property: KProperty<*>): List<Relation> {
val archetype = thisRef.archetype
override fun get(query: Query): List<Relation> {
val archetype = query.archetype
if (archetype != cachedArchetype) {
cachedArchetype = archetype
cachedRelations = archetype.getRelations(kind, target)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import com.mineinabyss.geary.systems.accessors.FamilyMatching
import com.mineinabyss.geary.systems.accessors.ReadOnlyAccessor
import com.mineinabyss.geary.systems.accessors.RelationWithData
import com.mineinabyss.geary.systems.query.Query
import kotlin.reflect.KProperty

@OptIn(UnsafeAccessors::class)
class RelationsWithDataAccessor<K, T>(
Expand All @@ -24,16 +23,16 @@ class RelationsWithDataAccessor<K, T>(
private var cachedRelations = emptyList<Relation>()
private var cachedArchetype: Archetype? = null

override fun getValue(thisRef: Query, property: KProperty<*>): List<RelationWithData<K, T>> {
val archetype = thisRef.archetype
override fun get(query: Query): List<RelationWithData<K, T>> {
val archetype = query.archetype
if (archetype != cachedArchetype) {
cachedArchetype = archetype
cachedRelations = archetype.getRelations(kind, target)
}

@Suppress("UNCHECKED_CAST")
return archetype.readRelationDataFor(
thisRef.row,
query.row,
kind,
target,
cachedRelations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ data class SystemBuilder<T : Query>(
}

inline fun exec(crossinline run: T.(T) -> Unit): TrackedSystem<*> {
val onTick: CachedQuery<T>.() -> Unit = { forEach(run) }
val onTick: CachedQuery<T>.() -> Unit = { forEach { run(it) } }
val system = System(name, query, onTick, interval)
return pipeline.addSystem(system)
}

inline fun <R> defer(crossinline run: T.() -> R): DeferredSystemBuilder<T, R> {
inline fun <R> defer(crossinline run: T.(T) -> R): DeferredSystemBuilder<T, R> {
val onTick: CachedQuery<T>.() -> List<CachedQuery.Deferred<R>> = {
mapWithEntity { run() }
mapWithEntity { run(it) }
}
val system = DeferredSystemBuilder(this, onTick)
return system
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,13 @@ class CachedQuery<T : Query> internal constructor(val query: T) {
return collected
}

inline fun <R> map(crossinline run: (T) -> R): List<R> {
inline fun <R> map(crossinline run: T.(T) -> R): List<R> {
val deferred = mutableListOf<R>()
forEach { deferred.add(run(it)) }
return deferred
}

inline fun <R> mapNotNull(crossinline run: (T) -> R?): List<R> {
inline fun <R> mapNotNull(crossinline run: T.(T) -> R?): List<R> {
val deferred = mutableListOf<R>()
forEach { query -> run(query).let { if (it != null) deferred.add(it) } }
return deferred
Expand Down Expand Up @@ -171,7 +171,7 @@ class CachedQuery<T : Query> internal constructor(val query: T) {
)

@OptIn(UnsafeAccessors::class)
inline fun <R> mapWithEntity(crossinline run: T.() -> R): List<Deferred<R>> {
inline fun <R> mapWithEntity(crossinline run: T.(T) -> R): List<Deferred<R>> {
val deferred = mutableListOf<Deferred<R>>()
forEach {
deferred.add(Deferred(run(it), it.unsafeEntity))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,34 @@ abstract class ShorthandQuery : Query() {
}

abstract class ShorthandQuery1<A> : ShorthandQuery() {
abstract val comp1: A
val comp1 get() = component1()

abstract operator fun component1(): A
}

abstract class ShorthandQuery2<A, B> : ShorthandQuery() {
abstract val comp1: A
abstract val comp2: B
val comp1 get() = component1()
val comp2 get() = component2()

abstract operator fun component1(): A
abstract operator fun component2(): B
}

abstract class ShorthandQuery3<A, B, C> : ShorthandQuery() {
abstract val comp1: A
abstract val comp2: B
abstract val comp3: C
val comp1 get() = component1()
val comp2 get() = component2()
val comp3 get() = component3()

abstract operator fun component1(): A
abstract operator fun component2(): B
abstract operator fun component3(): C
}

abstract class ShorthandQuery4<A, B, C, D> : ShorthandQuery() {
abstract val comp1: A
abstract val comp2: B
abstract val comp3: C
abstract val comp4: D
val comp1 get() = component1()
val comp2 get() = component2()
val comp3 get() = component3()
val comp4 get() = component4()

abstract operator fun component1(): A
abstract operator fun component2(): B
Expand All @@ -49,11 +49,11 @@ abstract class ShorthandQuery4<A, B, C, D> : ShorthandQuery() {
}

abstract class ShorthandQuery5<A, B, C, D, E> : ShorthandQuery() {
abstract val comp1: A
abstract val comp2: B
abstract val comp3: C
abstract val comp4: D
abstract val comp5: E
val comp1 get() = component1()
val comp2 get() = component2()
val comp3 get() = component3()
val comp4 get() = component4()
val comp5 get() = component5()

abstract operator fun component1(): A
abstract operator fun component2(): B
Expand All @@ -78,9 +78,9 @@ inline fun <reified A> query(
filterFamily?.let { this { it() } }
}

override val comp1 by getPotentiallyNullable<A>()
private val accessor1 = getPotentiallyNullable<A>()

override fun component1() = comp1
override fun component1() = accessor1.get(this)
}

inline fun <reified A, reified B> query(
Expand All @@ -92,11 +92,11 @@ inline fun <reified A, reified B> query(
filterFamily?.let { this { it() } }
}

override val comp1 by getPotentiallyNullable<A>()
override val comp2 by getPotentiallyNullable<B>()
private val accessor1 = getPotentiallyNullable<A>()
private val accessor2 = getPotentiallyNullable<B>()

override fun component1(): A = comp1
override fun component2(): B = comp2
override fun component1(): A = accessor1.get(this)
override fun component2(): B = accessor2.get(this)
}


Expand All @@ -109,13 +109,13 @@ inline fun <reified A, reified B, reified C> query(
filterFamily?.let { this { it() } }
}

override val comp1 by getPotentiallyNullable<A>()
override val comp2 by getPotentiallyNullable<B>()
override val comp3 by getPotentiallyNullable<C>()
private val accessor1 = getPotentiallyNullable<A>()
private val accessor2 = getPotentiallyNullable<B>()
private val accessor3 = getPotentiallyNullable<C>()

override fun component1(): A = comp1
override fun component2(): B = comp2
override fun component3(): C = comp3
override fun component1(): A = accessor1.get(this)
override fun component2(): B = accessor2.get(this)
override fun component3(): C = accessor3.get(this)
}

inline fun <reified A, reified B, reified C, reified D> query(
Expand All @@ -127,15 +127,15 @@ inline fun <reified A, reified B, reified C, reified D> query(
filterFamily?.let { this { it() } }
}

override val comp1 by getPotentiallyNullable<A>()
override val comp2 by getPotentiallyNullable<B>()
override val comp3 by getPotentiallyNullable<C>()
override val comp4 by getPotentiallyNullable<D>()
private val accessor1 = getPotentiallyNullable<A>()
private val accessor2 = getPotentiallyNullable<B>()
private val accessor3 = getPotentiallyNullable<C>()
private val accessor4 = getPotentiallyNullable<D>()

override fun component1(): A = comp1
override fun component2(): B = comp2
override fun component3(): C = comp3
override fun component4(): D = comp4
override fun component1(): A = accessor1.get(this)
override fun component2(): B = accessor2.get(this)
override fun component3(): C = accessor3.get(this)
override fun component4(): D = accessor4.get(this)
}

inline fun <reified A, reified B, reified C, reified D, reified E> query(
Expand All @@ -147,17 +147,17 @@ inline fun <reified A, reified B, reified C, reified D, reified E> query(
filterFamily?.let { this { it() } }
}

override val comp1 by getPotentiallyNullable<A>()
override val comp2 by getPotentiallyNullable<B>()
override val comp3 by getPotentiallyNullable<C>()
override val comp4 by getPotentiallyNullable<D>()
override val comp5 by getPotentiallyNullable<E>()

override fun component1(): A = comp1
override fun component2(): B = comp2
override fun component3(): C = comp3
override fun component4(): D = comp4
override fun component5(): E = comp5
private val accessor1 = getPotentiallyNullable<A>()
private val accessor2 = getPotentiallyNullable<B>()
private val accessor3 = getPotentiallyNullable<C>()
private val accessor4 = getPotentiallyNullable<D>()
private val accessor5 = getPotentiallyNullable<E>()

override fun component1(): A = accessor1.get(this)
override fun component2(): B = accessor2.get(this)
override fun component3(): C = accessor3.get(this)
override fun component4(): D = accessor4.get(this)
override fun component5(): E = accessor5.get(this)
}

@JvmName("toList1")
Expand Down
Loading

0 comments on commit 578d72e

Please sign in to comment.