web: accelerate and measure wallet startup - #58
Conversation
There was a problem hiding this comment.
I measured the branch on a throttled link before reading the diff, so the numbers below are mine rather than a re-read of the description.
What I tested:
- Staged the
v0.1.0runtime asset set, built the demo, and measured cold load then reload in the same browser context at 50 Mbps using the instrumentation this PR adds. ColdwasmTotalwas 3232 ms withwasmCompileInstantiateat 3230 ms, and the sample carried{"path":"gzip","streaming":true,"decompression":"http"}, so theContent-Encoding: gzipstreaming route works end to end. - The reload paid the same 3253 ms. Repeat-fetching the module in the page kept
transferSizeat 19,929,433 bytes on all three loads while a ~1 MiB control asset served with identical headers dropped to 0 after the first, so the browser really is declining to store it. pnpm build,pnpm typecheck(all 8 projects) andpnpm --filter @lightninglabs/wavelength-web testare clean. I didn't run the Playwright smoke suite.
One finding doesn't fit inline, because the file isn't part of this diff:
The reference doc's compressed-loading description is now false, and the new API is undocumented. apps/docs/src/content/docs/reference/wavelength-web.mdx:362 says the client "prefers the gzip-compressed wavewalletdk.wasm.gz binary, inflating it through a DecompressionStream and instantiating the resulting bytes." Under the configuration this PR's READMEs now tell hosts to adopt, it does neither. These pages are hand-maintained: scripts/gen-api-docs.mts only writes apps/docs/src/data/api/wallet.json, so nothing regenerates them.
Newly public surface is also missing there: onPerformance on WebClientOptions (wavelength-web.mdx:37) and on WalletEngineOptions (wavelength-core.mdx:419), the new optional parameter on registerPasskeyWallet and assertPasskeyPrf, and createWebPasskeyCeremony entirely. Grepping onPerformance across both reference pages returns nothing. api-links.ts needs the new export too.
Worth noting that #59 adds the Content-Type and Content-Encoding guidance to hosting-runtime-assets.mdx, so that gap closes in the stack. The reference pages are untouched by #59 and stay stale through both.
b466545 to
84f4313
Compare
84f4313 to
164ff12
Compare
In this commit, we add opt-in structured performance events across runtime startup, WebAssembly loading, wallet RPCs, state adoption, sync polling, and passkey ceremonies. The reporter is isolated from wallet behavior, so a failing diagnostic callback cannot disrupt operations. We also stream HTTP-decompressed gzip content directly into WebAssembly compilation when the host advertises the correct headers. Existing buffered gzip and raw WASM paths remain as fallbacks.
In this commit, we add repeatable Playwright samples for cold load, create, reload, and unlock, with checked-in p95 budgets and a single-attempt state-adoption constraint. The demo opts into structured samples only when the harness installs its callback. We also serve precompressed WASM with the headers required by the streaming path and document how to reproduce measurements with pinned or local runtime assets.
164ff12 to
1d1110e
Compare
The wasm loader was rewritten rather than patchedHeads up that this PR's diff has changed shape since the last review. The header handling turned into a permutation table that kept producing findings: six rounds of review, each one patching one more combination of The root cause was that the loader tried to predict what the body was from headers and then recover when the prediction was wrong, which meant the recovery had to know which prediction it made. That is what bred the flags. It now reads the first four bytes and branches on the magic number instead ( Three practical consequences:
The smoke test now serves the compressed asset as raw gzip so the SDK's own inflate path gets real-browser coverage; the benchmark keeps the transport-inflates configuration so its recorded numbers stay comparable. Worth re-reviewing |
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. |
Summary
In this PR, we make browser wallet startup measurable and move the
precompressed WASM artifact onto the browser's native streaming compilation
path. When a host serves
wavewalletdk.wasm.gzasapplication/wasmwithContent-Encoding: gzip, the browser can decompress and compile the module inone pipeline. The existing buffered gzip and raw WASM paths remain as
fallbacks.
We also add opt-in structured performance samples for runtime readiness, WASM
loading, wallet create and unlock RPCs, post-RPC state adoption, sync polling,
and passkey ceremonies. The web demo uses those samples in a repeatable
Playwright benchmark with checked-in p95 budgets.
Technical Notes
Instrumentation stays disabled unless the caller supplies
onPerformance.Timing calls and event allocations are skipped in that case. A diagnostic
callback is isolated from wallet behavior, so an exception from the reporter
cannot break an operation.
The benchmark creates a fresh browser context and wallet for every sample. It
also fails if
getInfoadoption needs more than one attempt. The latestfive-run result using
lightninglabs/wavelength#1048reported:To separate the two contributions, the SDK and HTTP/WASM changes were measured
before applying the public-KDF optimization:
improvement.
clientReadyp95 fell from 307 ms to 260 ms, a 47 ms or 15%improvement.
seconds. There was no meaningful operation-level improvement from the SDK
changes alone.
The larger operation gains come from the dependent public-KDF change:
approximately 0.9 seconds from create and 0.55 seconds from unlock. The private
KDF remains unchanged.
Steps to Test
Run the package tests:
Run workspace checks and builds:
Stage a local Wavelength runtime and run the browser budget:
Related Issues & Pull Requests
Closes #53
Depends on: