Entity-Component-System Benchmarks for .NET

April 8, 2026 · View on GitHub

License Stars

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.

Unity Version

Frameworks:

ECSVersionImplemented
DragonECS0.9.21
FriFlo3.6.0
LeoECSLite2025.4.22
Massive ECSv20.1.1
Morpeh2024.1.1
StaticEcs2.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:

  1. Spawn / Respawn / Kill
  2. Render current state into framebuffer
  3. Update unit sprite state
  4. Apply damage from pending attacks
  5. Create new attacks
  6. Move units
  7. Update velocity
  8. 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

  1. Install .NET 10 SDK and NPM

  2. Clone repository

    git clone --recursive https://github.com/cNoNim/ecs-benchmark-runner-dotnet.git
    
  3. Run tests

    dotnet test Ecs.Benchmark.Dotnet.slnx
    
  4. Run benchmarks

    dotnet run --project Benchmark.Runner -c Release -- --filter '*'
    

    Run benchmarks for both .NET 10 and NativeAOT 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.

RepositoryProject
Dragon ECSBenchmark.DragonEcs
FriFlo ECSBenchmark.FrifloEcs
LeoEcsLiteBenchmark.EcsLite
Massive ECSBenchmark.MassiveEcs
MorpehBenchmark.Morpeh
StaticEcsBenchmark.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.