Skip to main content

cwright trace

cwright trace <flow.parquet> [--entity N] [--server RESOURCE:N] [--limit N]

Reads a flow-record Parquet file back and prints one entity's history or one physical server's work log — the question a summary statistic cannot answer: why was this specific lot late, and what was this specific machine doing while it happened. Exactly one of --entity or --server is required.

Flags​

FlagMeaning
--entity NEvery recorded step for entity N, in the order it visited them.
--server RESOURCE:NEvery recorded step handled by server N of resource RESOURCE, both given as their internal indices.
--limit NCap the number of rows printed (default 60); the total count and an aggregate are always printed even when the output is truncated.

⚠️⚠️ An entity id can name more than one lot, and nothing here can tell​

An entity id is an entity slot plus a reuse counter, and the counter is 12 bits wide — so after 4,095 reuses of one slot the same id is handed out again. That margin is generous for a fab: a plant holding three thousand lots at once and releasing a hundred and seventy thousand reuses each slot about fifty times. ⭐ It is not generous at the other end — a small model run for a long time — and that is what an analytical target or a benchmark looks like. Measured on an M/M/1 at 70% utilisation over 3,000,000 seconds: 2,998,093 lots released with 44 alive at the peak, and one id carrying four different lots, exactly 4,096 seconds apart.

⚠️ So on a long run of a small model, --entity N can select the rows of several different lots, and the closing total then describes a lot that never existed. trace does not detect this, and the plausible way to detect it does not work: "one lot visits each step once" is false, because a rework loop revisits its steps, and the visit column counts only rework passes at the loop head — it is reset as the lot moves on. Timestamps do not separate the cases either, since rows are written in completion order, so a merged id's times run in order too.

⭐ How to keep lot identities unique: keep released per replication well under 4,095 × peak_live_entities, which the results document reports for every run. Shortening the horizon works; more replications do not, because each replication runs the full horizon.

Output​

ENTITY STEP VISIT RES SRV ARRIVED QUEUED SETUP PROCESS
4471 2 1 0 1 182930000 1200000 0 45000000
...

37 records: 12500000 ticks queued, 291000000 ticks processing (4.1% of the time was waiting)

Times are in ticks (see Determinism — divide by a model's tick_scale_per_second to convert to seconds). The closing line is a quick sanity check on its own: a high proportion of time queued relative to processing, for one entity or one server, is usually the first sign of where a bottleneck actually is.

Getting a flow file​

Flow records are written by run --flow DIR, one Parquet file per replication. See The results document for the full schema and how to query it directly with pandas, Polars, or DuckDB instead of trace — trace is for looking at one entity or server by eye; the Parquet file itself is for everything else.