Files
admin b9a24b3fb5 Step 11: benchmark host fast-path, decision = keep
Adds benchmarks/host-fast-path.py and benchmarks/README.md.

The benchmark compares two paths for a cached single-ID search:
  1. fast-path: in-process dict walk inside the native host
     (handle_cached_search_fast in rcjav-host.py)
  2. subprocess: shell out to `rc-jav.py --search ID --cache --format json`

Idle baseline against the live 7124-file cache (5 queries × 5 iter):

  fast-path:   median 0.46ms  p95 0.61ms  max 0.72ms
  subprocess:  median 919ms   p95 1233ms  max 1385ms
  median speedup: 2000x

Decision: keep the fast path. The ~920ms subprocess cost is dominated
by Python interpreter startup + 1.3MB cache.json parse. That's
structural — it applies under idle Python too, not just when a scan
is running. The "Python actively scanning" condition from the original
roadmap doesn't change the verdict; it would only make the subprocess
path even slower while leaving the in-process path unaffected (the
fast path doesn't touch the scanning process).

The fast path is already correctly scoped — bails out for wildcards,
ranges, name searches, and --quick mode. Narrowing further would just
push more queries through the slow path with no upside.

Possible follow-up (not in scope here): memoize _load_host_cache with
mtime-based invalidation so the fast path doesn't reparse cache.json
on every call. Current per-call median (0.46ms) is already fast enough
that this is optional.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 11:12:33 +02:00

67 lines
2.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# benchmarks/
Latency benchmarks for decisions in the rc-jav roadmap.
## host-fast-path.py — Step 11 decision
The native-messaging host has an in-process fast path
(`handle_cached_search_fast` in `rcjav-host.py`) that answers simple
cached single-ID searches without shelling out to `rc-jav.py`. Step 11
asked: is the fast path actually pulling its weight, or could we
delete it / narrow it down?
### Run
```
python benchmarks/host-fast-path.py [--queries Q1 Q2 ...] [--iterations N]
```
For the "Python actively scanning" condition, start `rc-jav.py --scan`
in a separate terminal first.
### Findings (idle baseline, 2026-05-23, 7124-file cache)
```
=== aggregate (5 queries × 5 iterations, idle Python) ===
fast-path total:
n=25 min=0.43ms median=0.46ms mean=0.48ms p95=0.61ms max=0.72ms
subprocess total:
n=25 min=880.56ms median=919.45ms mean=965.55ms p95=1232.93ms max=1385.37ms
median speedup: 2000.1x
p95 speedup: 2036.0x
```
### Decision: keep the fast path
The subprocess path costs ~920ms median per query even with the
interpreter doing nothing else — that's pure Python startup +
`json.loads` of the 1.3 MB cache.json. The fast path returns hits in
under 1ms. The 2000× speedup is structural (interpreter startup
overhead), not load-dependent, so it would apply equally under (a)
idle and (b) active-scan conditions.
The fast path is already correctly scoped — it bails out for
wildcards, ranges, name searches, and `--quick` mode (which forces a
live rclone hit). Narrowing further would just push more queries
through the slow path with no upside.
The "Python actively scanning" condition listed in the original
roadmap was framed as the case where the fast path's value would be
most obvious. The idle baseline already settles it; we don't need to
gate the decision on the active-scan measurement, though running it
remains a sanity check if cache.json grows substantially.
### What this benchmark does NOT cover
- Latency from inside the browser extension (popup) to the host. Adds
Brave's native-messaging protocol overhead on top of whichever path
the host takes — but the relative difference between paths is
preserved.
- Memory cost of the in-process cache load. The fast path loads
cache.json once per call today (no caching across calls inside the
host). A future optimization is to memoize `_load_host_cache` with
mtime-based invalidation; left for follow-up if needed.
- Cold-cache effects. `cache.json` is large enough that the OS page
cache matters; numbers above reflect a warm read. First call after
a reboot may be slower for both paths but proportionally so.