[browser][coreCLR] R2R: Interpreter live hotness trigger for on-demand R2R shard download
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
# Interpreter live hotness trigger for on-demand R2R shard download
Part of #130524.
Status: **draft / issue candidate** · Area: CoreCLR interpreter, runtime lazy-load · Related: #130517 (counters), #130523 (R2R-only boot asset), #130515 (IL shard consumer), #130522 (entry-point patch). Rides the upstream webcil-in-wasm async loader (#129634). **Required for the R1 demo.**
## Goal
Give the interpreter a live, in-process mechanism that detects when a method (or loop) has become hot and triggers a request to fetch and activate its precompiled (R2R) shard — the runtime half of R1's "stream what's hot" behavior. This must operate during ordinary execution, with **no diagnostics/EventPipe session open**.
## Why
The interpreter counters (#130517) feed the **offline** profile export used at build time to select the startup composite (carried out over EventPipe via #130518). They do not, by themselves, drive anything at runtime. R1's defining behavior — the interpreter observing hot code and pulling in its R2R shard in the background — needs a **live threshold-and-trigger loop** that runs in normal app runs. Without it, lazy tier-up never happens, so even the prototype demo (composite plus lazy shard tier-up) cannot exercise the runtime streaming path. This is a normal-execution feature, not a diagnostics one.
## Direction
- **Reuse the interpreter's hotness counters** (the same per-method and loop counters introduced by #130517) but add a **runtime threshold check**: when a method crosses the hot threshold, fire a trigger.
- **Own the async R2R-shard fetch and install.** On the trigger, ensure the method's IL shard is resident (via the shard consumer), then asynchronously fetch the method's R2R shard and install it in the async continuation — reusing the browser host's webcil-in-wasm instantiate path (grow the table, instantiate the module) — and finally patch the entry point (via the entry-point work). The interpreter keeps running the method meanwhile.
- **Consume the R2R-only boot-config asset.** Use the R2R-only asset entry the splitter emits into the boot configuration to locate and size the shard, and to map the hot method to it.
- **Independent of EventPipe.** It must work with no profiling session open and add negligible overhead when disabled.
- **Async-tolerant.** The interpreter keeps running the method interpreted while the shard is fetched and instantiated in the background; the entry point is upgraded when ready and picked up on the method's next call (no on-stack replacement).
- **De-duplicate and back off.** Avoid repeated requests for the same method/shard; handle in-flight and already-satisfied requests gracefully.
## Scope
**In:** the interpreter-side hotness threshold and trigger; owning the async R2R-shard fetch and install (reusing the browser host's async webcil-in-wasm instantiate) with the IL shard ensured resident first; consuming the R2R-only boot-config asset to locate the shard; de-duplication and back-pressure; the enable/disable switch and low idle overhead.
**Out:** the counters themselves as a profile producer (#130517); the entry-point patch itself (#130522); IL-shard loading (#130515); the offline profile export (#130518); build-time R2R production.
## Relationship to other items
This work is the trigger and **owns the async R2R-shard fetch/install**; it relies on the shard consumer (#130515) for the IL shard, the entry-point work (#130522) for the final patch, and the splitter (#130523) for the R2R-only boot-config asset. The interpreter counters are shared with the offline producer (#130517) and this live trigger — one counter, two consumers, as intended.
## Success criteria
- In a normal run with no EventPipe, a method that becomes hot triggers its R2R shard to load and its entry point to upgrade, and subsequent calls run native — demonstrable in the prototype.
- Negligible overhead when the feature is off.
## Open questions
- Threshold policy: call count, loop back-edge count, or both; fixed versus adaptive; where loop back-edge counting fits.
- The trigger contract shared with the shard consumer and R2R lazy loader, so a hot method and its shard arrive coherently (shared with the shard consumer's open question, #130515).
- Behavior when a method's shard is unavailable or fails to load (stay interpreted).
- Whether to persist the hot set for earlier tier-up on subsequent runs (relates to the local-storage idea) — likely a later extension.
> [!NOTE]
> This issue was drafted with GitHub Copilot assistance.
Contributor guide
Assessment
This issue has not been assessed yet.