Entity-Component-System Benchmarks for .NET
April 8, 2026 · View on GitHub
This repository contains a collection of benchmarks for .NET Entity-Component-System (ECS) frameworks. Benchmarks perform a complex performance comparison of ECS frameworks on a near-real-world scenario.
Frameworks:
| ECS | Version | Implemented |
|---|---|---|
| DragonECS | 0.9.21 | ✅ |
| FriFlo | 3.6.0 | ✅ |
| LeoECSLite | 2025.4.22 | ✅ |
| Massive ECS | v20.1.1 | ✅ |
| Morpeh | 2024.1.1 | ✅ |
| StaticEcs | 2.0.3 | ✅ |
Scenario
All benchmark implementations run the same deterministic simulation.
At startup, the benchmark creates N units. During spawn, each unit receives a type (NPC, Hero, or Monster), combat stats, position, and movement state. Each tick then runs the same gameplay pipeline: spawning and respawning, target selection, attack creation, damage application, movement, velocity updates, and rendering into a framebuffer.
This makes the benchmark closer to a small RTS-like combat loop than to a synthetic ECS microbenchmark.
Tick Pipeline
Each benchmark context executes the same logical steps:
- Spawn / Respawn / Kill
- Render current state into framebuffer
- Update unit sprite state
- Apply damage from pending attacks
- Create new attacks
- Move units
- Update velocity
- Advance simulation data
Validation
Benchmark implementations are validated by shared tests. For the same entity count and tick count, all contexts must produce the same framebuffer hash. This ensures the comparison is based on equivalent simulation results, not on different behavior.
Running
-
Install .NET 10 SDK and NPM
-
Clone repository
git clone --recursive https://github.com/cNoNim/ecs-benchmark-runner-dotnet.git -
Run tests
dotnet test Ecs.Benchmark.Dotnet.slnx -
Run benchmarks
dotnet run --project Benchmark.Runner -c Release -- --filter '*'Run benchmarks for both
.NET 10andNativeAOT 10.0:dotnet run --project Benchmark.Runner -c Release -- --filter '*' --runtimes net10.0 nativeaot10.0
Structure
The benchmark is divided into repositories. Current repository integrates benchmark packages into runner and test projects for .NET.
Benchmark.Core Package
A separate repository contains common assemblies that are used by benchmarks or by infrastructure. Integration is done in the Benchmark.Core project.
Benchmark.Generator
Part of Benchmark.Core package.
Benchmark.Generator is a source generator that checks referenced assemblies and looks for implementations of Benchmark.Core.IContext and generates Benchmark.Contexts.Factories that are used to get all the contexts involved in the benchmark.
Integration is done in the Benchmark.Generator project.
Benchmark Projects
Each benchmark is a separate repository, integration is done through separate projects in the Benchmarks folder.
| Repository | Project |
|---|---|
| Dragon ECS | Benchmark.DragonEcs |
| FriFlo ECS | Benchmark.FrifloEcs |
| LeoEcsLite | Benchmark.EcsLite |
| Massive ECS | Benchmark.MassiveEcs |
| Morpeh | Benchmark.Morpeh |
| StaticEcs | Benchmark.StaticEcs |
Dependencies
Dependencies folder contains integration projects for frameworks.
Frameworks can be referenced:
- as NuGet packages if the option is provided;
- as NPM git packages, if the benchmark integration is an NPM package;
- otherwise as a git submodule in the Submodules folder.
Benchmark.Template
Contains template project for benchmark integration.
Benchmark.Runner
Runner application runs benchmarks using BenchmarkDotNet.
Runner includes all benchmarks from the Benchmarks folder.
Additional runtime combinations can be selected via BenchmarkDotNet command line arguments such as --runtimes net10.0 nativeaot10.0.
Benchmark.Tests
Contains unit test project that validates that each benchmark produces the same state.