A high-performance Entity Component System for Dart.
Data-oriented simulation speed for games and apps — on Flutter, web, Jaspr, and CLI.
ecsly puts entities in cache-friendly archetypes, hot state in packed typed columns with SIMD views, and structural changes behind deferred command queues with explicit flush boundaries. Steady simulation frames run without allocating. The core is pure Dart — no Flutter dependency, no native code — and runs wherever Dart runs.
| Metric | Result | Signal |
|---|---|---|
| Raw chunk iteration (30k entities) | 81.2M ops/s | strongest hot query path |
| In-place typed-column mutation (30k) | 62.4M ops/s | zero-allocation component updates |
| Render-packet extract (30k) | 59.2M ops/s | simulation to Float32 payload for hosts |
| 20k-entity game frame, p95 | 769 µs | update + extract + flush per frame |
| Query at 100k entities | 65.1M ops/s | flat throughput from 1k to 100k |
| RSS growth, repeated frames (15k) | 16 KiB | near-zero allocation in steady state |
Median of 5 samples on MacBookAir10,1 (Apple M1, 16.0 GiB), Dart 3.13.4, commit b6bfef612134, 2026-11-06.
Reproduce: cd core_packages/ecsly && dart run benchmark/run.dart --limits --samples=5.
Full scorecard: benchmark/results/latest.md.
Prerelease 0.1.x: the API is still evolving; pin your version and follow the
CHANGELOG.
dart pub add ecslyimport 'package:ecsly/ecsly.dart';
class CounterComponent extends Component {
CounterComponent(this.value);
int value;
}
void main() {
final world = World();
world.components.registerObjectComponent<CounterComponent>();
final entity = world.reserveEmptyEntity().entity;
world.spawnBundle(entity, ComponentBundle.fromLists([CounterComponent(1)]));
world.flush();
world.createSchedule(ScheduleId.update).add((world) {
for (final (_, counter) in world.queryMut<CounterComponent>()) {
counter.value += 1;
}
});
world.runSchedule(ScheduleId.update);
world.flush();
}Requires Dart SDK >=3.12.0. To run the examples from source:
git clone https://github.com/Arenukvern/ecsly && cd ecsly
dart pub get
cd core_packages/ecsly
dart run example/main.dart| Example | Shows |
|---|---|
basic_world.dart |
Smallest object-component flow |
scheduled_run.dart |
Systems and schedules |
extension_component.dart |
Typed facade over hot column data |
commands_and_resources.dart |
Deferred commands and resources |
simd_columns.dart |
Stride-4 FloatColumn and SIMD views |
| I want to... | Start here |
|---|---|
| Run a headless simulation | Quick start, then the core examples above |
| Build game or simulation logic | ecsly README: schedules, queries, events |
| Speed up a hot loop | Typed columns + SIMD |
| Connect a Flutter UI | ecsly_flutter README |
| Structure app workflows | ecsly_app README: actions, drafts, invalidation |
| Generate typed-column factories | ecsly_codegen README |
| Save and load worlds | ecsly_serialization README |
| Record and replay simulations | ecsly_replay README |
| Contribute | CONTRIBUTING.md |
See the package map for sources and design records.
- Archetype storage. Entities with the same component set share packed
dart:typed_datacolumns; queries iterate contiguous memory. - Two component tiers. Object components for everyday modeling; typed
extension components put hot numeric state in
FloatColumn/IntColumnwith SIMD (Float32x4List) views. - Deferred structural changes. Spawns, despawns, and add/remove go through
command queues and apply at explicit
flush()boundaries — iteration stays stable and deterministic. - Cached queries. Query results cache against a topology epoch that advances once per structural flush.
Deep dives: core DESIGN_FAQ · architecture diagram.
ecsly owns simulation: entities, components, queries, systems, schedules,
events, commands, and resources. Rendering, input, physics, and audio belong
to the host — Flutter via ecsly_flutter, Jaspr, or your own engine layer.
The repo charter lives in docs/NORTH_STAR.mdx;
positioning and claim rules in
ADR 0005.
- Hosted docs: docs.page/arenukvern/ecsly
- Core package: README · DX FAQ · DESIGN FAQ · API
- Package map: docs/packages.mdx
- Decisions: docs/decisions/
Contributions are welcome on the packages and docs in this repo. Start with CONTRIBUTING.md; docs follow docs/VOICE.mdx.
- Pull request checklist: .github/pull_request_template.md
- Contributor credit: docs/contributing/contributors.mdx
- Security reports: GitHub security advisories
Thanks to everyone who helps improve ecsly.
This roster is maintained with all-contributors. Use the all-contributors bot or CLI from a pull request:
npx all-contributors-cli add <github-login> code,doc
npx all-contributors-cli generateDual-licensed under MIT and Apache-2.0.