All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jvmMain.stress.EngineStressTest.kt Maven / Gradle / Ivy

There is a newer version: 2021.0.3-RELEASE
Show newest version
package stress

import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.runBlocking
import org.hexworks.amethyst.api.Attribute
import org.hexworks.amethyst.api.Context
import org.hexworks.amethyst.api.Engine
import org.hexworks.amethyst.api.entity.Entity
import org.hexworks.amethyst.api.entity.EntityType
import org.hexworks.amethyst.api.newEntityOfType
import org.hexworks.amethyst.api.system.Behavior
import org.hexworks.amethyst.internal.TurnBasedEngine
import org.hexworks.cobalt.core.api.UUID
import java.util.concurrent.Executors
import kotlin.reflect.KClass
import kotlin.system.measureNanoTime

@Suppress("BlockingMethodInNonBlockingContext")
object EngineStressTest {

    private val target: TurnBasedEngine =
        Engine.create(Executors.newFixedThreadPool(1).asCoroutineDispatcher())

    @JvmStatic
    fun main(args: Array) {
        runManyEntitiesTest()
    }

    fun runManyEntitiesTest() = runBlocking {
        executeStressTestWith(1_000_000, 10000, ::createNoOpEntity)
    }

    fun runLongWorkingEntitiesTest() = runBlocking {
        executeStressTestWith(100, 500) {
            createWaitingEntity(it, 1)
        }
    }

    private suspend fun executeStressTestWith(
        entityCount: Int,
        repeats: Int,
        entityBuilder: (Int) -> Entity
    ) {
        repeat(entityCount) {
            target.addEntity(entityBuilder(it))
        }
        var counter = 0
        var timeSumMs = 0L
        repeat(repeats) {
            val nano = measureNanoTime {
                target.executeTurn(TestContext).join()
            }
            counter++
            timeSumMs += nano / 1000 / 1000
            if (counter == 100) {
                counter = 0
                val measurement = timeSumMs / 100
                timeSumMs = 0
                println("Average update time for $entityCount entities after 100 iterations: ${measurement}ms")
            }
        }
    }

    private fun createNoOpEntity(idx: Int): Entity {
        return newEntityOfType(TestEntityType) {
            attributes(
                TestAttribute(
                    name = "name $idx",
                    age = idx
                )
            )
            facets(TestFacet)
        }
    }

    private fun createWaitingEntity(idx: Int, waitMs: Long): Entity {
        return newEntityOfType(TestEntityType) {
            attributes(
                TestAttribute(
                    name = "name $idx",
                    age = idx
                )
            )
            facets(TestFacet)
            behaviors(WaitingBehavior(waitMs))
        }
    }

    class WaitingBehavior(private val waitMs: Long) : Behavior {

        override val id: UUID = UUID.randomUUID()
        override val mandatoryAttributes: Set> = setOf()

        override suspend fun update(entity: Entity, context: C): Boolean {
            Thread.sleep(waitMs)
            return true
        }

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy