Huxpro / Huxpro/lynx-js-framework-benchmark
Native element-pipeline attribution: probe the LepusNG seam and clock first, then stage counts before self-time
- Dominant language
- JavaScript
- Stars
- 2
- Forks
- 2
- Avg merge
- 1d 5h
- Merged PRs (30d)
- 33
Description
Extends #28/#29 to the device. #29's web split (engine self-time inside ElementPAPI vs the framework's own JS) is measured inside lynx-web-core — a polyfill. On device the same seam would measure the **real native engine + JNI bridge**. If the engine/framework shares agree across web and native, the web pipeline lane earns its device-predictor stake quantitatively — the calibration #42 B could not deliver by cross-framework timing.
#29 itself scoped this out honestly ("Native has no framework-neutral ElementPAPI seam"). The seam question is decidable in one cheap lease, so decide it before designing anything bigger.
## N0 — the probe lease (one window, two questions, no matrix)
1. **Wrappability.** On `aries_10`, in the MTS Lepus context: are the PAPI builtins (`__CreateView`, `__FlushElementTree`, …) rebindable globals? Prepend a shim to a known-good bundle's MTS section via the existing round-3 build patching (`scripts/build-app.mjs` / `issue194-native-instrument.mjs`): `const orig = __CreateView; __CreateView = function(){ probe.count++; return orig.apply(this, arguments) }` — then paint 100 rows and read the counter back over the existing evidence channel. Rebind throws or is silently ignored → the seam does not exist, record that and stop; the native pipeline stays out of scope with evidence instead of assumption.
2. **Clock resolution.** What is the finest timer the Lepus context exposes? (`performance.now` was observed degraded to `Date.now` in round 1 — re-verify, and check for `lynx.performance` or any high-resolution alternative.) Record resolution and monotonicity. Single PAPI calls are ~10µs; a millisecond clock cannot measure self-time but costs nothing to rule in or out.
Both answers are one checked-in record. The staging below is gated on them.
## N1 — counts matrix (requires wrappability only)
Per-segment **call counts** via the shim (classification reused verbatim from `packages/shared/src/pipeline.mjs` — same six segments, same `classifyPapiMethod`), for octane-hux / upstream / ReactLynx at 1k (and 7k for octane per the known ceiling). Counts are exact, resolution-free, and near-zero overhead.
Payoff even without timing: verifies the web counts transfer 1:1 to device (70k/60k-shape rows, the #242 element accounting) or exposes where the native lowering differs — either answer is calibration. Oracle: octane-hux create@1k counts equal the web pipeline lane's counts exactly, or the diff is itemized by method name.
## N2 — self-time matrix (requires a high-resolution clock)
Only if N0's clock answer permits: port the #29 wrapper semantics — including the **frame-stack self-time** (`self = elapsed − childMs`; nesting under `__FlushElementTree` must not double-count) and the `ΣPAPI ≤ operation` acceptance invariant. Overhead discipline via three arms per the C11/C12 methodology: **unwrapped / count-only / timed**, same bundle otherwise; if the timed arm's overhead is not separable from the signal (interpreter clock reads × 200k calls may dominate), publish counts only and say why — a fold-to-constant arm removes more than the code it deleted.
Deliverable if N2 lands: engine-bill share native vs web per workload, one table. That is the calibration statement.
## Boundaries
- Native pipeline records are a **new suite** (`pipeline-native` or similar), isolated exactly as #29 isolated web pipeline from table/startup — never in the Native ranking cohort, never merged with web pipeline records. Harness separation untouched.
- On-device wrapped self-time includes the JNI bridge; label it "engine + bridge, as seen from Lepus" — that *is* the bill the framework's caller pays, but name it honestly.
- Vendored frozen bundles (ReactLynx) get the shim by MTS-section prefixing, not by rebuild — record the exact injection in the evidence, same as the round-3 instruments.
Sequencing: N0 fits in any upcoming lease (can share one with the #43 re-run's device work if a lease is already planned). N1/N2 are their own windows. #29 merge order is unaffected — this builds on its shared vocabulary, not its branch.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with scripts/build-app.mjs and issue194-native-instrument.mjs, then inspect the shared classification in packages/shared/src/pipeline.mjs. Run the N0 probe on aries_10 using a known-good MTS bundle, checking PAPI rebinding and timer resolution. Done means a checked-in record of wrappability, resolution, and monotonicity; later count or timing matrices are gated on those results.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- performance, testing
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100