Skip to content

Commit

Permalink
adding package-benchmark sub-project (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
heckj authored Oct 10, 2024
1 parent 0b3ba92 commit e0ee97b
Show file tree
Hide file tree
Showing 5 changed files with 335 additions and 1 deletion.
3 changes: 2 additions & 1 deletion .codecov.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
ignore:
- "Tests/"
- "Benchmarks/"

comment:
layout: header, changes, diff
layout: header, changes, diff
85 changes: 85 additions & 0 deletions Benchmarks/Benchmarks/ECSBenchmark/Base.swift
Original file line number Diff line number Diff line change
@@ -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
}
198 changes: 198 additions & 0 deletions Benchmarks/Benchmarks/ECSBenchmark/OneDimensionBenchmarks.swift
Original file line number Diff line number Diff line change
@@ -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
}
)
}
}
}
28 changes: 28 additions & 0 deletions Benchmarks/Package.swift
Original file line number Diff line number Diff line change
@@ -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")
]
)
]
)
22 changes: 22 additions & 0 deletions Benchmarks/README.md
Original file line number Diff line number Diff line change
@@ -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).

0 comments on commit e0ee97b

Please sign in to comment.