adding package-benchmark sub-project (#64)
This commit is contained in:
parent
0b3ba9241b
commit
e0ee97bd7f
|
|
@ -1,5 +1,6 @@
|
||||||
ignore:
|
ignore:
|
||||||
- "Tests/"
|
- "Tests/"
|
||||||
|
- "Benchmarks/"
|
||||||
|
|
||||||
comment:
|
comment:
|
||||||
layout: header, changes, diff
|
layout: header, changes, diff
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
//
|
||||||
|
// Base.swift
|
||||||
|
// FirebladeECSTests
|
||||||
|
//
|
||||||
|
// Created by Christian Treffs on 09.10.17.
|
||||||
|
//
|
||||||
|
|
||||||
|
import FirebladeECS
|
||||||
|
|
||||||
|
class EmptyComponent: Component {}
|
||||||
|
|
||||||
|
class Name: Component {
|
||||||
|
var name: String
|
||||||
|
init(name: String) {
|
||||||
|
self.name = name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Position: Component {
|
||||||
|
var x: Int
|
||||||
|
var y: Int
|
||||||
|
init(x: Int, y: Int) {
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Velocity: Component {
|
||||||
|
var a: Float
|
||||||
|
init(a: Float) {
|
||||||
|
self.a = a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Party: Component {
|
||||||
|
var partying: Bool
|
||||||
|
init(partying: Bool) {
|
||||||
|
self.partying = partying
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Color: Component {
|
||||||
|
var r: UInt8 = 0
|
||||||
|
var g: UInt8 = 0
|
||||||
|
var b: UInt8 = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExampleSystem {
|
||||||
|
private let family: Family2<Position, Velocity>
|
||||||
|
|
||||||
|
init(nexus: Nexus) {
|
||||||
|
family = nexus.family(requiresAll: Position.self, Velocity.self, excludesAll: EmptyComponent.self)
|
||||||
|
}
|
||||||
|
|
||||||
|
func update(deltaT _: Double) {
|
||||||
|
for (position, velocity) in family {
|
||||||
|
position.x *= 2
|
||||||
|
velocity.a *= 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class SingleGameState: SingleComponent {
|
||||||
|
var shouldQuit: Bool = false
|
||||||
|
var playerHealth: Int = 67
|
||||||
|
}
|
||||||
|
|
||||||
|
func setUpNexus() -> Nexus {
|
||||||
|
let numEntities = 10000
|
||||||
|
let nexus = Nexus()
|
||||||
|
|
||||||
|
for i in 0 ..< numEntities {
|
||||||
|
nexus.createEntity().assign(Position(x: 1 + i, y: 2 + i),
|
||||||
|
Name(name: "myName\(i)"),
|
||||||
|
Velocity(a: 3.14),
|
||||||
|
EmptyComponent(),
|
||||||
|
Color())
|
||||||
|
}
|
||||||
|
|
||||||
|
precondition(nexus.numEntities == numEntities)
|
||||||
|
// precondition(nexus.numFamilies == 1)
|
||||||
|
precondition(nexus.numComponents == numEntities * 5)
|
||||||
|
|
||||||
|
return nexus
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,198 @@
|
||||||
|
// swiftformat:disable preferForLoop
|
||||||
|
import Benchmark
|
||||||
|
import FirebladeECS
|
||||||
|
|
||||||
|
// derived from FirebladeECSPerformanceTests/TypedFamilyPerformanceTests.swift in the parent project
|
||||||
|
|
||||||
|
let benchmarks = {
|
||||||
|
Benchmark("TraitMatching") { benchmark in
|
||||||
|
let nexus = setUpNexus()
|
||||||
|
let a = nexus.createEntity()
|
||||||
|
a.assign(Position(x: 1, y: 2))
|
||||||
|
a.assign(Name(name: "myName"))
|
||||||
|
a.assign(Velocity(a: 3.14))
|
||||||
|
a.assign(EmptyComponent())
|
||||||
|
|
||||||
|
let isMatch = nexus.family(requiresAll: Position.self, Velocity.self,
|
||||||
|
excludesAll: Party.self)
|
||||||
|
|
||||||
|
for _ in benchmark.scaledIterations {
|
||||||
|
blackHole(
|
||||||
|
isMatch.canBecomeMember(a)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Benchmark("TypedFamilyEntities") { benchmark in
|
||||||
|
let nexus = setUpNexus()
|
||||||
|
let family = nexus.family(requires: Position.self, excludesAll: Party.self)
|
||||||
|
for _ in benchmark.scaledIterations {
|
||||||
|
blackHole(
|
||||||
|
family
|
||||||
|
.entities
|
||||||
|
.forEach { (entity: Entity) in
|
||||||
|
_ = entity
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Benchmark("TypedFamilyOneComponent") { benchmark in
|
||||||
|
let nexus = setUpNexus()
|
||||||
|
let family = nexus.family(requires: Position.self, excludesAll: Party.self)
|
||||||
|
for _ in benchmark.scaledIterations {
|
||||||
|
blackHole(
|
||||||
|
family
|
||||||
|
.forEach { (position: Position) in
|
||||||
|
_ = position
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Benchmark("TypedFamilyEntityOneComponent") { benchmark in
|
||||||
|
let nexus = setUpNexus()
|
||||||
|
let family = nexus.family(requires: Position.self, excludesAll: Party.self)
|
||||||
|
for _ in benchmark.scaledIterations {
|
||||||
|
blackHole(
|
||||||
|
family
|
||||||
|
.entityAndComponents
|
||||||
|
.forEach { (entity: Entity, position: Position) in
|
||||||
|
_ = entity
|
||||||
|
_ = position
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Benchmark("TypedFamilyTwoComponents") { benchmark in
|
||||||
|
let nexus = setUpNexus()
|
||||||
|
let family = nexus.family(requiresAll: Position.self, Velocity.self, excludesAll: Party.self)
|
||||||
|
for _ in benchmark.scaledIterations {
|
||||||
|
blackHole(
|
||||||
|
family
|
||||||
|
.forEach { (position: Position, velocity: Velocity) in
|
||||||
|
_ = position
|
||||||
|
_ = velocity
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Benchmark("TypedFamilyEntityTwoComponents") { benchmark in
|
||||||
|
let nexus = setUpNexus()
|
||||||
|
let family = nexus.family(requiresAll: Position.self, Velocity.self, excludesAll: Party.self)
|
||||||
|
for _ in benchmark.scaledIterations {
|
||||||
|
blackHole(
|
||||||
|
family
|
||||||
|
.entityAndComponents
|
||||||
|
.forEach { (entity: Entity, position: Position, velocity: Velocity) in
|
||||||
|
_ = entity
|
||||||
|
_ = position
|
||||||
|
_ = velocity
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Benchmark("TypedFamilyThreeComponents") { benchmark in
|
||||||
|
let nexus = setUpNexus()
|
||||||
|
let family = nexus.family(requiresAll: Position.self, Velocity.self, Name.self, excludesAll: Party.self)
|
||||||
|
for _ in benchmark.scaledIterations {
|
||||||
|
blackHole(
|
||||||
|
family
|
||||||
|
.forEach { (position: Position, velocity: Velocity, name: Name) in
|
||||||
|
_ = position
|
||||||
|
_ = velocity
|
||||||
|
_ = name
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Benchmark("TypedFamilyEntityThreeComponents") { benchmark in
|
||||||
|
let nexus = setUpNexus()
|
||||||
|
let family = nexus.family(requiresAll: Position.self, Velocity.self, Name.self, excludesAll: Party.self)
|
||||||
|
for _ in benchmark.scaledIterations {
|
||||||
|
blackHole(
|
||||||
|
family
|
||||||
|
.entityAndComponents
|
||||||
|
.forEach { (entity: Entity, position: Position, velocity: Velocity, name: Name) in
|
||||||
|
_ = entity
|
||||||
|
_ = position
|
||||||
|
_ = velocity
|
||||||
|
_ = name
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Benchmark("TypedFamilyFourComponents") { benchmark in
|
||||||
|
let nexus = setUpNexus()
|
||||||
|
let family = nexus.family(requiresAll: Position.self, Velocity.self, Name.self, Color.self, excludesAll: Party.self)
|
||||||
|
for _ in benchmark.scaledIterations {
|
||||||
|
blackHole(
|
||||||
|
family
|
||||||
|
.forEach { (position: Position, velocity: Velocity, name: Name, color: Color) in
|
||||||
|
_ = position
|
||||||
|
_ = velocity
|
||||||
|
_ = name
|
||||||
|
_ = color
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Benchmark("TypedFamilyEntityFourComponents") { benchmark in
|
||||||
|
let nexus = setUpNexus()
|
||||||
|
let family = nexus.family(requiresAll: Position.self, Velocity.self, Name.self, Color.self, excludesAll: Party.self)
|
||||||
|
for _ in benchmark.scaledIterations {
|
||||||
|
blackHole(
|
||||||
|
family
|
||||||
|
.entityAndComponents
|
||||||
|
.forEach { (entity: Entity, position: Position, velocity: Velocity, name: Name, color: Color) in
|
||||||
|
_ = entity
|
||||||
|
_ = position
|
||||||
|
_ = velocity
|
||||||
|
_ = name
|
||||||
|
_ = color
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Benchmark("TypedFamilyFiveComponents") { benchmark in
|
||||||
|
let nexus = setUpNexus()
|
||||||
|
let family = nexus.family(requiresAll: Position.self, Velocity.self, Name.self, Color.self, EmptyComponent.self, excludesAll: Party.self)
|
||||||
|
|
||||||
|
for _ in benchmark.scaledIterations {
|
||||||
|
blackHole(
|
||||||
|
family
|
||||||
|
.forEach { (position: Position, velocity: Velocity, name: Name, color: Color, empty: EmptyComponent) in
|
||||||
|
_ = position
|
||||||
|
_ = velocity
|
||||||
|
_ = name
|
||||||
|
_ = color
|
||||||
|
_ = empty
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Benchmark("TypedFamilyEntityFiveComponents") { benchmark in
|
||||||
|
let nexus = setUpNexus()
|
||||||
|
let family = nexus.family(requiresAll: Position.self, Velocity.self, Name.self, Color.self, EmptyComponent.self, excludesAll: Party.self)
|
||||||
|
|
||||||
|
for _ in benchmark.scaledIterations {
|
||||||
|
blackHole(family
|
||||||
|
.entityAndComponents
|
||||||
|
.forEach { (entity: Entity, position: Position, velocity: Velocity, name: Name, color: Color, empty: EmptyComponent) in
|
||||||
|
_ = entity
|
||||||
|
_ = position
|
||||||
|
_ = velocity
|
||||||
|
_ = name
|
||||||
|
_ = color
|
||||||
|
_ = empty
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
// swift-tools-version: 5.8
|
||||||
|
|
||||||
|
import PackageDescription
|
||||||
|
|
||||||
|
let package = Package(
|
||||||
|
name: "ECSBenchmarks",
|
||||||
|
platforms: [
|
||||||
|
.iOS(.v16),
|
||||||
|
.macOS(.v13)
|
||||||
|
],
|
||||||
|
dependencies: [
|
||||||
|
.package(path: "../"),
|
||||||
|
.package(url: "https://github.com/ordo-one/package-benchmark", .upToNextMajor(from: "1.4.0"))
|
||||||
|
],
|
||||||
|
targets: [
|
||||||
|
.executableTarget(
|
||||||
|
name: "ECSBenchmark",
|
||||||
|
dependencies: [
|
||||||
|
.product(name: "FirebladeECS", package: "ecs"),
|
||||||
|
.product(name: "Benchmark", package: "package-benchmark")
|
||||||
|
],
|
||||||
|
path: "Benchmarks/ECSBenchmark",
|
||||||
|
plugins: [
|
||||||
|
.plugin(name: "BenchmarkPlugin", package: "package-benchmark")
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Benchmarks for FirebladeECS
|
||||||
|
|
||||||
|
Originally seeded by replicating performance tests into a new form leveraging [package-benchmark](https://swiftpackageindex.com/ordo-one/package-benchmark/) [Documentation](https://swiftpackageindex.com/ordo-one/package-benchmark/main/documentation/benchmark).
|
||||||
|
|
||||||
|
To run all the available benchmarks:
|
||||||
|
|
||||||
|
swift package benchmark --format markdown
|
||||||
|
|
||||||
|
For more help on the package-benchmark SwiftPM plugin:
|
||||||
|
|
||||||
|
swift package benchmark help
|
||||||
|
|
||||||
|
Creating a local baseline:
|
||||||
|
|
||||||
|
swift package --allow-writing-to-package-directory benchmark baseline update dev
|
||||||
|
swift package benchmark baseline list
|
||||||
|
|
||||||
|
Comparing to a the baseline 'alpha'
|
||||||
|
|
||||||
|
swift package benchmark baseline compare dev
|
||||||
|
|
||||||
|
For more details on creating and comparing baselines, read [Creating and Comparing Benchmark Baselines](https://swiftpackageindex.com/ordo-one/package-benchmark/main/documentation/benchmark/creatingandcomparingbaselines).
|
||||||
Loading…
Reference in New Issue