v0.2.0 80c61e3

performance.md RawHistoryFolder

Performance measurement

vev measures the current session and attachment stack with process-local runtime marks and harness-owned end-to-end boundaries. Measurement does not alter rendering, pacing, transport policy, wire bytes, or ProtocolVersion.

Canonical matrix

The canonical matrix is testdata/perf/manifest.json:

  • topologies 1x4, 4x1, 4x4, and 8x1;
  • 120x40 terminal content with 10,000 history rows per pane;
  • idle, active output, all/inactive output, interactive flood, copy search, resize sweep, snapshot/output/resize, and attach/restore/tab switch;
  • local, SSH stdio, direct UDP, UDP with 25/100 ms latency, and UDP with 0%/1% loss.

The matrix contains 252 scenarios (4 topologies × 9 workloads × 7 transports). Inapplicable scenarios stay present with an explicit reason. Multiple-attachment scenarios measure shared session mutations together with independent attachment views and output streams.

A connection handshake is bounded by 15 seconds. A command request is bounded by 10 seconds. These limits apply during measurement as well as normal use.

Trace schema and clocks

Every process JSONL record has exactly these fields: schema, process_id, component, scenario, run, sequence, request_id, epoch, kind, tick, bytes, fragments, retransmits, pending, ack_rtt_nanos, and valid.

Schema 1 is represented by:

{"schema":1,"process_id":"p","component":"daemon","scenario":"s","run":1,"sequence":1,"request_id":1,"epoch":1,"kind":"diff_start","tick":0,"bytes":0,"fragments":0,"retransmits":0,"pending":0,"ack_rtt_nanos":0,"valid":true}

The concrete JSONL observer stamps tick with its process-local injected monotonic clock; producers supply no timestamp. Components in one OS process share that observer. The harness owns a separate monotonic clock for the input-injection to successfully-flushed-terminal-bytes boundary. Ticks from different processes or clock domains are never ordered or subtracted. Records correlate through scenario, run, sequence, request, and epoch IDs.

Process-local spans cover capture, compose, diff, queue wait, acknowledgement blocking, emit, adapter send, and adapter receive. Bytes, fragments, retransmits, pending work, and acknowledgement RTT remain diagnostics rather than duration inputs. Reports retain raw records, counts, p50/p95/p99, and max where applicable.

Running the matrix

Use a clean build and at least a 10-second warmup, a 30-second measured interval, and ten independent repetitions:

go build -o /tmp/vev ./
rm -rf testdata/perf/results
go run ./cmd/vev-perf-harness \
  --vev-bin /tmp/vev \
  --manifest testdata/perf/manifest.json \
  --out testdata/perf/results \
  --warmup 10s --duration 30s --repetitions 10

Each run writes manifest.json, raw-harness.jsonl, one trace per launched process, runs.json, and summary.json. The process manifest records process identity, role, scenario/run, clock domain, and its exclusive trace path.

The harness injects at most one measured event per second. A sample requires both input injection and successful terminal flush inside the measured interval; warmup, straddling, and failed events remain raw diagnostics. Reject results with missing or unmatched boundaries, invalid correlation, nonmonotonic same-process sequence, negative same-domain duration, fewer than 10 complete in-interval pairs, invalid denominators, cross-process tick math, less than 30 seconds measured, or fewer than 10 repetitions.

Before a full run, validate the manifest and harness:

jq -e '(.topologies|length)==4 and (.workloads|length)==9 and (.transports|length)==7 and (.scenarios|length)==252' testdata/perf/manifest.json
go test ./cmd/vev-perf-harness

For a bounded local check, add --scenario 1x4-idle-local. The harness still validates the complete manifest before selecting that scenario. Do not commit result directories; raw traces and run manifests are the measurement evidence.

In-process checks

These commands measure local daemon or VT work only, not end-to-end transport latency:

go test ./internal/usecase/daemon -run '^$' -bench '^BenchmarkDaemonHistory' -benchtime=1x -benchmem
go test ./pkg/renderer ./pkg/vt ./internal/adapters/ipc -run '^$' -bench=. -benchmem
go test ./internal/usecase/daemon -run '^$' -bench '^BenchmarkComposeCapturedFloatingFrameCached$' -benchmem
source
1# Performance measurement
2
3vev measures the current session and attachment stack with process-local runtime
4marks and harness-owned end-to-end boundaries. Measurement does not alter
5rendering, pacing, transport policy, wire bytes, or `ProtocolVersion`.
6
7## Canonical matrix
8
9The canonical matrix is [`testdata/perf/manifest.json`](../testdata/perf/manifest.json):
10
11- topologies `1x4`, `4x1`, `4x4`, and `8x1`;
12- `120x40` terminal content with 10,000 history rows per pane;
13- idle, active output, all/inactive output, interactive flood, copy search,
14  resize sweep, snapshot/output/resize, and attach/restore/tab switch;
15- local, SSH stdio, direct UDP, UDP with 25/100 ms latency, and UDP with 0%/1%
16  loss.
17
18The matrix contains 252 scenarios (4 topologies × 9 workloads × 7
19transports). Inapplicable scenarios stay present with an explicit reason.
20Multiple-attachment scenarios measure shared session mutations together with
21independent attachment views and output streams.
22
23A connection handshake is bounded by 15 seconds. A command request is bounded
24by 10 seconds. These limits apply during measurement as well as normal use.
25
26## Trace schema and clocks
27
28Every process JSONL record has exactly these fields:
29`schema`, `process_id`, `component`, `scenario`, `run`, `sequence`, `request_id`,
30`epoch`, `kind`, `tick`, `bytes`, `fragments`, `retransmits`, `pending`,
31`ack_rtt_nanos`, and `valid`.
32
33Schema 1 is represented by:
34
35```json
36{"schema":1,"process_id":"p","component":"daemon","scenario":"s","run":1,"sequence":1,"request_id":1,"epoch":1,"kind":"diff_start","tick":0,"bytes":0,"fragments":0,"retransmits":0,"pending":0,"ack_rtt_nanos":0,"valid":true}
37```
38
39The concrete JSONL observer stamps `tick` with its process-local injected
40monotonic clock; producers supply no timestamp. Components in one OS process
41share that observer. The harness owns a separate monotonic clock for the
42input-injection to successfully-flushed-terminal-bytes boundary. Ticks from
43different processes or clock domains are never ordered or subtracted. Records
44correlate through scenario, run, sequence, request, and epoch IDs.
45
46Process-local spans cover capture, compose, diff, queue wait, acknowledgement
47blocking, emit, adapter send, and adapter receive. Bytes, fragments,
48retransmits, pending work, and acknowledgement RTT remain diagnostics rather
49than duration inputs. Reports retain raw records, counts, p50/p95/p99, and max
50where applicable.
51
52## Running the matrix
53
54Use a clean build and at least a 10-second warmup, a 30-second measured
55interval, and ten independent repetitions:
56
57```sh
58go build -o /tmp/vev ./
59rm -rf testdata/perf/results
60go run ./cmd/vev-perf-harness \
61  --vev-bin /tmp/vev \
62  --manifest testdata/perf/manifest.json \
63  --out testdata/perf/results \
64  --warmup 10s --duration 30s --repetitions 10
65```
66
67Each run writes `manifest.json`, `raw-harness.jsonl`, one trace per launched
68process, `runs.json`, and `summary.json`. The process manifest records process
69identity, role, scenario/run, clock domain, and its exclusive trace path.
70
71The harness injects at most one measured event per second. A sample requires
72both input injection and successful terminal flush inside the measured
73interval; warmup, straddling, and failed events remain raw diagnostics. Reject
74results with missing or unmatched boundaries, invalid correlation,
75nonmonotonic same-process sequence, negative same-domain duration, fewer than
7610 complete in-interval pairs, invalid denominators, cross-process tick math,
77less than 30 seconds measured, or fewer than 10 repetitions.
78
79Before a full run, validate the manifest and harness:
80
81```sh
82jq -e '(.topologies|length)==4 and (.workloads|length)==9 and (.transports|length)==7 and (.scenarios|length)==252' testdata/perf/manifest.json
83go test ./cmd/vev-perf-harness
84```
85
86For a bounded local check, add `--scenario 1x4-idle-local`. The harness still
87validates the complete manifest before selecting that scenario. Do not commit
88result directories; raw traces and run manifests are the measurement evidence.
89
90## In-process checks
91
92These commands measure local daemon or VT work only, not end-to-end transport
93latency:
94
95```sh
96go test ./internal/usecase/daemon -run '^$' -bench '^BenchmarkDaemonHistory' -benchtime=1x -benchmem
97go test ./pkg/renderer ./pkg/vt ./internal/adapters/ipc -run '^$' -bench=. -benchmem
98go test ./internal/usecase/daemon -run '^$' -bench '^BenchmarkComposeCapturedFloatingFrameCached$' -benchmem
99```

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 12

Tags 11

↑↓ moveenter openesc close