Files
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
..

Launch Benchmark

Single-JVM warm benchmark for the cold-boot critical path. See desktopApp/plans/2026-06-17-feat-app-launch-optimization-plan.md for the design.

Run

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_inAccountManager.accountState reaches LoggedIn(isReadOnly=true).
  • t_first_event — first kind:1 flows through DesktopLocalCache.consume.
  • t_n_eventsnth (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.