Goke
High-performance, zero-allocation ECS for Go. Cache-friendly data orchestrator with type-safe iterators.
Install / Use
/learn @kjkrol/GokeREADME
GOKe
<p align="center"> <img src=".github/docs/img/logo.png" alt="GOKe Logo" width="300"> <br> <a href="https://go.dev"> <img src="https://img.shields.io/badge/Go-1.23+-00ADD8?style=flat-square&logo=go" alt="Go Version"> </a> <a href="https://pkg.go.dev/github.com/kjkrol/goke"> <img src="https://img.shields.io/badge/GoDoc-Reference-007d9c?style=flat-square&logo=go" alt="GoDoc"> </a> <a href="https://opensource.org/licenses/MIT"> <img src="https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square" alt="License"> </a> <a href="https://github.com/kjkrol/goke/actions"> <img src="https://github.com/kjkrol/goke/actions/workflows/go.yml/badge.svg" alt="Go Quality Check"> </a> </p>GOKe is an ultra-lightweight, high-performance, and type-safe Entity Component System (aka ECS) for Go. It is engineered for maximum data throughput, leveraging modern Go 1.23+ Iterators and a Data-Oriented Design (DOD) architecture.
<p align="center"> <a href="#installation">Installation</a> • <a href="#usage">Usage</a> • <a href="#architecture">Architecture</a> • <a href="#performance">Performance</a> • <a href="#features">Features</a> • <a href="#roadmap">Roadmap</a> • <a href="BENCHMARKS.md">Benchmarks</a> • <a href="#documentation">Documentation</a> </p>🚀 Use Cases: Why GOKe?
GOKe is primarily a high-performance ECS for game development, designed to manage massive entity counts while keeping the Go Garbage Collector (GC) completely silent. However, its core architecture a data-oriented orchestrator — makes it suitable for any scenario requiring cache-friendly iteration over millions of objects.
🎮 Gaming (Ebitengine & Frameworks)
GOKe is the perfect companion for Ebitengine or purely server-side game loops. Managing thousands of active objects (bullets, particles, NPCs) often hits CPU bottlenecks due to pointer chasing and GC pressure. GOKe solves this via:
- Zero-Alloc Updates: Update thousands of entities in a single tick without triggering the GC.
- Decoupled Logic: Keep your rendering logic in Ebitengine and your game state in GOKe's optimized archetypes, utilizing structures like Bucket Grid.
- Deterministic Physics: Run complex collision detection systems across all entities using
RunParallel.
🧬 Simulations & High-Throughput Data
Beyond gaming, GOKe shines in any domain where latency consistency is critical and object counts are in the millions.
- Agent-Based Simulations: Crowd dynamics, epidemiological models, or particle physics where $O(N)$ iteration speed is the bottleneck.
- Real-time Telemetry: Processing high-frequency data streams (e.g., IoT sensor fusion) where predictable memory access patterns prevent latency spikes.
- Heavy Compute Pipelines: Logic that requires transforming large datasets every frame (e.g., 16ms window) without allocation overhead.
⚖️ When NOT to use GOKe
To ensure GOKe is the right tool for your project, consider these trade-offs:
- Small Data Sets: If you only manage a few hundred objects, a simple slice of structs will be easier to maintain and fast enough.
- Deep Hierarchies: ECS is designed for flat, high-speed iteration. If your data is naturally a deep tree (like a UI DOM), a classic tree structure might be more intuitive.
- High Structural Churn: If you are adding/removing components from thousands of entities every single frame, the overhead of archetype migration might offset the iteration gains.
<a id="installation"></a>
📦 Installation
GOKe requires Go 1.23 or newer.
go get github.com/kjkrol/goke
<a id="features"></a>
✨ Key Features
Core capabilities designed for predictable performance, cache locality, and zero-allocation cycles:
- Type-Safe Generics: Views (
NewView1[A]...NewView8) use Go generics to eliminate interface overhead, boxing, and runtime type assertions in the hot loop. - Go 1.23+ Range Iterators: Uses native
iter.Seqfor standardfor rangeloops. This allows the compiler to inline iteration logic directly, avoiding callback overhead. - Deferred Mutations: Structural changes (Create/Remove/Add components) are buffered via a Command Buffer and applied at synchronization points to ensure thread safety without heavy locking.
- Parallel Execution:
RunParalleldistributes system execution across available CPU cores with deterministic synchronization, scaling linearly with hardware resources. - Zero-Alloc Hot Loop: The architecture guarantees zero heap allocations during the update cycle (tick), preventing GC pauses during simulation.
- Entity Blueprints: Fast, template-based instantiation. Allows creating thousands of entities with identical component layouts using optimal memory copy operations.
💡 See it in action: Check the
cmddirectory for the concurrent dice game simulation demonstrating parallel systems and state management.
<a id="usage"></a>
💻 Usage Example
📘 New to ECS? Check out the Getting Started with GOKe guide for a step-by-step deep dive into building your first simulation.
package main
import (
"fmt"
"time"
"github.com/kjkrol/goke"
)
type Pos struct{ X, Y float32 }
type Vel struct{ X, Y float32 }
type Acc struct{ X, Y float32 }
func main() {
// Initialize the ECS world.
// The ECS instance acts as the central coordinator for entities and systems.
ecs := goke.New()
// Define component metadata.
// This binds Go types to internal descriptors, allowing the engine to
// pre-calculate memory layouts and manage data in contiguous arrays.
posDesc := goke.RegisterComponent[Pos](ecs)
_ = goke.RegisterComponent[Vel](ecs)
_ = goke.RegisterComponent[Acc](ecs)
// --- Type-Safe Entity Template (Blueprint) ---
// Blueprints place the entity into the correct archetype immediately and
// reserve memory for all components in a single atomic operation.
// This returns typed pointers for direct, in-place initialization.
blueprint := goke.NewBlueprint3[Pos, Vel, Acc](ecs)
// Create the entity and get direct access to its memory slots.
entity, pos, vel, acc := blueprint.Create()
*pos = Pos{X: 0, Y: 0}
*vel = Vel{X: 1, Y: 1}
*acc = Acc{X: 0.1, Y: 0.1}
// Initialize view for Pos, Vel, and Acc components
view := goke.NewView3[Pos, Vel, Acc](ecs)
// Define the movement system using the functional registration pattern
movementSystem := goke.RegisterSystemFunc(ecs, func(schedule *goke.Schedule, d time.Duration) {
// SoA (Structure of Arrays) layout ensures CPU Cache friendliness.
for head := range view.Values() {
pos, vel, acc := head.V1, head.V2, head.V3
vel.X += acc.X
vel.Y += acc.Y
pos.X += vel.X
pos.Y += vel.Y
}
})
// Configure the ECS's execution workflow and synchronization points
goke.Plan(ecs, func(ctx goke.ExecutionContext, d time.Duration) {
ctx.Run(movementSystem, d)
ctx.Sync() // Ensure all component updates are flushed and views are consistent
})
// Execute a single simulation step (standard 120 TPS)
goke.Tick(ecs, time.Second/120)
p, _ := goke.GetComponent[Pos](ecs, entity, posDesc)
fmt.Printf("Final Position: {X: %.2f, Y: %.2f}\n", p.X, p.Y)
}
Explore Examples
Check the examples/ directory for complete, ready-to-run projects.
⚠️ IMPORTANT: Setup Required: To keep the core ECS engine lightweight and free of GUI dependencies, examples are managed as isolated modules. Before running them, you must initialize the workspace:
make setup
- Mini Demo – The minimalist starter.
- Simple Demo – A slightly more advanced introduction to the ECS lifecycle.
- Parallel Demo – Advanced showcase:
- Coordination of multiple systems.
- Concurrent execution using
RunParallel. - Handling structural changes via Command Buffer and explicit Sync points.
- Ebiten Demo – Graphics Integration & Spatial Physics:
- Real-time rendering using Ebitengine.
- High-performance spatial management using GOKg.
- Custom physics pipeline: Velocity Inversion is processed strictly before Position Compensation to ensure boundary stability.
- Note: Run
makeinside the example directory to fetch dependencies and start the demo.
<a id="architecture"></a>
🏗️ Core Architecture & "Mechanical Sympathy"
GOKe is an archetype-based ECS designed for deterministic performance. It shifts structural overhead (like offset calc
