Performance Targets

Home | Status & Roadmap →


Core Budget: 512Hz = 1.95ms per Frame

PhaseBudgetTarget
PrePhysics0.4msUser logic, input, AI decisions
Physics Simulation0.8msJolt solver, collision, response
PostPhysics0.3msCollision callbacks, state updates
History Write0.2msTemporal ring buffer write
Overhead0.25msScheduling, atomics, profiling
TOTAL1.95ms512Hz target

Measured (2026-05, RelWithDebInfo)

TestResult
PrePhysics (100K entities)~0.1ms
PrePhysics (1M entities, stress test)~1.0ms
Full logic frame (100K, no physics)~0.3ms with propagation
25-layer pyramid (5,526 entities)~1ms steady, 14.67ms settling spike
100K cubes + 25-layer pyramid (logic)0.73ms steady, 18.74ms settling
205K entities (100K super + 5.5K phys)~1.4ms steady, ~28ms settling
Jolt step (25-layer settling)~12ms settling, <1ms steady

Render Thread

Target: 60–120 FPS (8–16ms per frame) for 100K visible entities.

PhaseBudgetStatus
History Access0.5msRead T-1 and T sections from slab
Culling + Interpolation3.0msFrustum cull, lerp, build InterpBuffer
State Sorting1.0msSort by 64-bit keys (pending)
GPU Upload1.5msDirty-bit selective transfer
Command Encoding2.0msBuild render pass
GPU Submit + Sync0.5msFrame fence, swapchain
TOTAL8.5ms**~117 FPS budget**

Measured

TestResult
100K cubes + 25-layer pyramid (render)~0.88ms (1133 FPS)
205K entities (settling)~3.1ms (320 FPS)
205K entities (steady)~1.5ms (660 FPS)

No frustum culling yet; all entities rendered. Dirty-bit-driven GPU upload operational — only modified entities uploaded per frame.


Input-to-Photon Latency

Target: <16ms (one frame @ 60Hz).

StageAvg
Input Sampling (Sentinel)0.5ms
Logic Processing (Brain)1.95ms (one 512Hz tick)
Render Frame (Encoder)0.7ms
GPU Execution + VSync16.6ms @ 60Hz monitor
Best case total18.75ms

Measured: ~9ms on 240Hz monitor steady state. ~14.3ms under heavy physics load (205K entities settling).


Rollback Performance

Target: <5ms for 128-frame resimulation.

MetricResult
Resim (5 frames, 100K entities)~18ms (full resim, no dirty propagation)
Resim (12 frames, 100K entities)~28ms (crosses 2 physics boundaries)
Jolt RestoreSnapshot<1ms (7KB via `StateRecorderImpl`)
ECS determinismByte-perfect (34MB memcmp)
Jolt determinismByte-perfect (7,436 bytes)
Per-frame SaveSnapshot overhead<0.1ms

Full frame resim includes PrePhysics + Physics Step + FlushPendingBodies + PullActiveTransforms + PostPhysics + PropagateFrame for every frame in the window. Dirty propagation (resim only corrected entities) is designed but not yet wired — expected to reduce resim cost by 10–100× for typical corrections affecting <1% of entities.


Scalability

Entity Count vs Logic Frame Time

Entity CountPrePhysics (512Hz)Notes
10K0.01msTrivial
50K0.08msComfortable
100K~0.1msPrimary target — achieved
1M~1.0msStress test only

Entity Count vs Render Frame Time (no culling)

CountRenderFPS
100K~0.88ms1133
205K (settling)~3.1ms320
205K (steady)~1.5ms660

Memory Targets

Per-Entity Hot Data (Approximate)

ComponentFieldsBytes/entity/frame
CTransform9 fields (pos/rot/scale)36B
CVelocity3 fields24B
CJoltBody4 fields~16B

Temporal Slab (100K entities)

Temporal slab size = MAX_CACHED_ENTITIES × bytes per entity × TemporalFrameCount. At 92 bytes/entity (ECS & Storage):

Ring depthHistory @ 512HzMemory
8 (minimum)~15.6ms~74MB
32 (engine default)~62.5ms~294MB
128 (editor / full rollback)~250ms~1.18GB

The 34MB figure in Rollback Netcode is the temporal field data compared byte-for-byte in the 2026-03-29 validation run, not the full ring allocation. Measured allocations scale with the configured MAX_CACHED_ENTITIES and component set — see EngineConfig::TemporalFrameCount.


Network

Target: 30Hz net tick, <5ms resim per correction.

MetricTarget
Packet send rate30Hz (configurable via NetworkUpdateHz)
Rollback window128 frames (~250ms @ 512Hz)
Resim time<5ms (pending dirty propagation optimization)
Delta compression ratio70–90%
Prediction accuracy>95%

UI (GG-UI)

A document costs what changed in it and what shows of it, not how big it is. Measured by GGUI_Scale on a document shaped like a tool's panel (sections of rows, each row two pieces of text and a button), on one core, with text at a fixed size per character so that the numbers are the UI core's own. The targets are for 100,000 nodes.

MetricTargetMeasured, 10,000 nodesMeasured, 100,000 nodes
An update with nothing changedno function, no layout, no publish (by counters)00
One changed label: buildone component's function0.0003 ms0.0005 ms
One changed label: layoutthe nodes whose size changed0.0002 ms0.0002 ms
One changed label: publishone row written; under 0.05 ms0.005 ms0.015 ms
Hit-testunder 0.01 ms0.0003 ms0.008 ms
Finding a node in a snapshotunder 0.001 msunder 0.0001 msunder 0.0001 ms
Memory a nodeunder 480 bytes470 bytes469 bytes
Build from nothingin proportion to the node count2.6 ms27 ms
Layout from nothingin proportion2.4 ms26 ms
Publish from nothingin proportion2.0 ms23 ms
The whole function again, nothing differentin proportion0.7 ms7.3 ms
Painting 10,000 primitives from nothingunder 0.5 ms0.20 ms—
A list scrolled a little: publishno row written; under 0.25 ms0.006 ms0.015 ms
A list of a million rows: a frame scrolled within a row, and past oneunder 0.1 ms and under 0.5 ms—0.003 ms and 0.05 ms (a million)
A table of a million rows in six columns: a frame scrolled within a row, past one, and with a column draggedunder 0.1 ms, 1 ms, and 2 ms—0.011 ms, 0.21 ms, and 0.22 ms (674 nodes)
A screen of 8,000 nodes built in order of priority, 0.5 ms a frame to build in: the longest frameunder 4 ms; 5.4 ms all at once1.8 ms, over five frames—

The test holds a run to the counts (one function, one row, nothing when idle, bytes a node) and, in an optimized build, to the times with room to spare. A document's function run again as a whole costs every element it builds, which is what components are for. What is not yet in proportion: a first frame (build, layout, and publish from nothing), at about 0.7 microseconds a node. A document can spread one over several frames by giving content a priority (BoxProps::Priority).


Benchmark Hardware

Tests run on:

  • Intel Core Ultra 9 275HX / AMD Ryzen 9 9950X
  • 32GB / 64GB RAM
  • RTX 5070 Ti / RTX 4070
  • CachyOS Arch Linux, Windows 11
  • Build: RelWithDebInfo

Profiling tools: Tracy (frame timing), MSVC assembly inspection, RenderDoc.