Files
amethyst/desktopApp/benchmarks/README.md
T
nrobi144 b14ee5ec5c feat(desktop): in-process relay seam, launch benchmark, bootstrap-gate removal
Phases 2.1/2.2/2.3, 3.1/3.2, 4, 5.2, and 6 of the launch-optimization plan
land together because they share a single set of seams and a single
benchmark report.

* InProcessWebsocketBuilder + LaunchFixtureRelay wrap quartz's existing
  InProcessWebSocket + NostrServer (with EmptyPolicy) so any test can
  drive a NostrClient against an in-memory relay seeded with arbitrary
  events. Roundtrip verified by LaunchFixtureRelayTest.

* LaunchFixture builds a deterministic 50-note synthetic home-feed
  snapshot from a fixed RNG seed (kind:1 + author kind:0 + kind:3 +
  kind:10002). A real-world JSONL artifact is a drop-in replacement.

* NoteCard gets a stable testTag + a CompositionLocal-backed
  onPlaced hook. Production overhead is one composition-local read
  plus one null check per placement (default
  LocalNoteCardInstrumentation = null).

* LaunchMarkers records named markers against TimeSource.Monotonic.
  LaunchScenario.coldBoot drives the AccountManager (ViewOnly path)
  + DesktopLocalCache + RelayConnectionManager + LocalRelayStore
  stack against the fixture relay and reports t_account_logged_in,
  t_first_event, t_n_events.

* LaunchBenchmark runs 2 warmup + 5 measured iterations, computes
  min/q1/median/q3/max, atomically writes the report file, and is
  skipped by default — opt in via AMETHYST_BENCH=true. Baseline +
  post-fix snapshots committed under desktopApp/benchmarks/.

* SubscribeBeforeConnectTest proves NostrClient / RelayPool queue REQs
  issued before connect() and flush them when the connection comes up.
  The bootstrap-config subscription in Main.kt drops its
  `connectedRelays.first { isNotEmpty() }` + 30s withTimeoutOrNull gate
  on the strength of that invariant — the subscription now fires
  eagerly and recovers when no relay ever connects instead of silently
  giving up after 30s.

All 274 desktopApp tests pass. No flaky tests introduced.
2026-06-18 11:10:14 +03:00

50 lines
1.8 KiB
Markdown

# Launch Benchmark
Single-JVM warm benchmark for the cold-boot critical path. See
[`desktopApp/plans/2026-06-17-feat-app-launch-optimization-plan.md`](../plans/2026-06-17-feat-app-launch-optimization-plan.md)
for the design.
## Run
```bash
AMETHYST_BENCH=true ./gradlew :desktopApp:test \
--tests "*LaunchBenchmark.run" --rerun-tasks
```
Without the env var the test class skips itself silently so a normal
`./gradlew :desktopApp:test` stays fast.
## Output
A per-git-sha report lands at
`desktopApp/build/benchmarks/launch-<git-sha>.txt`. The benchmark prints the
report to stdout and atomically writes the file via
`Files.move(... ATOMIC_MOVE)` so a killed run does not pollute the trend
data with partial content.
## Reading the numbers
Each row reports `n`, min, q1, median, q3, max in milliseconds. The
benchmark drives the slim "non-Compose" cold-boot scenario:
`AccountManager.loadSavedAccount` → relay subscription via
`InProcessWebsocketBuilder` (fixture relay) → `DesktopLocalCache.consume`.
- `t_account_logged_in``AccountManager.accountState` reaches
`LoggedIn(isReadOnly=true)`.
- `t_first_event` — first `kind:1` flows through `DesktopLocalCache.consume`.
- `t_n_events``n`th (default `n=10`) `kind:1` flows through the cache.
Numbers are dominated by the harness floor (`InProcessWebSocket` channel
hops, fixture-server REQ matching, coroutine dispatcher schedule). They
are most useful as a **regression guard** for code already in the
exercised path; they do **not** approximate a real Skia/Swing first paint.
Layered Compose-driven and JVM-fork variants are tracked as deferred
follow-ups in the plan.
## Snapshots committed here
- `baseline-main.txt` — pre-Phase-5.2 baseline.
- `with-phase5-fixes.txt` — post-Phase-5.2 snapshot.
Diff manually with `diff -u baseline-main.txt with-phase5-fixes.txt`.