Measure the RN → WebView pose-bridge latency #16
Notifications
Due Date
No due date set.
Blocks
#11 Decide: success gates and the measurement protocol
lars/splat-indoor-navigation
#14 Write the Session 1 spec (pose to splat rendering)
lars/splat-indoor-navigation
#17 Decide: does orientation bypass the bridge via DeviceOrientationEvent in the WebView?
lars/splat-indoor-navigation
Reference: lars/splat-indoor-navigation#16
Reference in New Issue
Block a user
Question
Both #3 and #6 independently landed on the same load-bearing unknown: nobody has published the one-way
injectJavaScriptpose-channel latency at 30–60Hz, and no splat frame rate inside WKWebView exists in the literature either. Two of the four proposed gates (#11) and the whole architecture bet in #14 rest on it. It is also cheap to settle — an afternoon, no splat required — which is why it is a task rather than a research ticket.Build the smallest possible probe:
react-native-webview, a page that does nothing but echo.performance.now()into a pose object and pushes it viainjectJavaScriptat a fixed rate; the page echoes it back viawindow.ReactNativeWebView.postMessageon the nextrequestAnimationFrame; RN logs the delta.Done when the numbers are posted here. They become the latency gate in #11 and the pose-channel design in #14.
Part of the wayfinder map #1.
Baseline and method, from #3's second addendum — this ticket is now partly answered and better specified.
Published Android numbers to measure against (discussion #3669): 31 ms postMessage round trip at 100 chars, with a ~10 ms floor on the RN→native command alone that is independent of payload size.
localhostHTTP measured 5.9 ms for the same payload — a ~5× win in exactly the pose regime.No published iOS figure exists, which is precisely why this ticket is worth an afternoon.
Add these arms to the probe:
injectJavaScriptper-frame at 10/30/60Hz — the baseline, expected to be the loser.requestAnimationFrame. Standard AR practice (late-stage reprojection); converts channel cost from per-frame to per-keyframe.react-native-webview; verify before designing around it.DeviceOrientationEventinside the WebView — zero-hop orientation, see #17.Method notes:
performance.now()with one measured offset, notDate.now().window.__setPosehandler once viainjectedJavaScriptBeforeContentLoaded; don't re-eval a source string per frame, and don't route pose through React state.postMessagecoerces withString(data)—JSON.stringifyexplicitly.injectJavaScripthas a double-dispatch history.Existing harness to port (targets the old architecture, so update it first): jamonholmgren/WebViewPing.
Correction to my earlier note on this ticket: the 10ms floor is Android-only.
Measured iOS figures do exist (see #3 addendum 3):
evaluateJavaScriptround trip 0.39ms andWKScriptMessageHandler0.63ms on iOS 9 / iPad Air 2, so ~0.2–1.5ms one-way extrapolated to current silicon. Per-frame injection at 60Hz on iOS is plausibly fine. The ~10ms floor and the 5× localhost win are the AndroidpostMessageprop path.So this probe's purpose shifts: less "is the bridge viable" and more "confirm it on modern hardware, and find what actually dominates". Revised arms, in priority order:
evaluateJavaScriptper-frame at 60Hz on the real iPhone — expected sub-millisecond. The 2015 benchmarks are the only published data and they predate modern silicon by a decade.ARSessionandWKWebViewin the same native module and injects straight fromsession(_:didUpdate:)withcompletionHandler: nil.react-native-webviewalways passes a non-nil block, paying WebKit's return-path cost (IPC result serialization + a JSContext). Measure both — if the delta is real it argues for a small native module rather than the RN bridge.rAFis hard-capped at 60Hz in WKWebView (WebKit 294338), so don't send faster and don't expect 120Hz on ProMotion.Method:
performance.now()with a measured offset againstARFrame.timestamp(mach uptime); report median and p95; physical device only. Do not put pose on the web→RN direction — Fabric'sonMessageis gated on the main run loop hittingBeforeWaiting, with no coalescing and no backpressure.