Skip to content

CLI: replay the report of unchanged files - #56

Merged
johanrd merged 2 commits into
mainfrom
perf-report-cache
Aug 29, 2026
Merged

johanrd merged 2 commits into
mainfrom
perf-report-cache

Conversation

@johanrd

@johanrd johanrd commented Aug 29, 2026

Copy link
Copy Markdown
Owner

validate-gts now caches each file's deduplicated html-validate report under node_modules/.cache/html-validate-ember/report/, keyed by the file's content, the resolved .htmlvalidate.json configuration, html-validate's version, the tsconfig (through Glint) and the environment switches. On a hit the file is not validated: its stored report feeds the same counters and the same formatter output. HVE_NO_CACHE=1 bypasses it like the Glint and transform caches; the plugin-source hash invalidates it on every plugin change.

This is the CLI-level counterpart of #55: #55 skips the template work when html-validate still runs (editor hosts, html-validate's own CLI); this skips html-validate itself when validate-gts runs. Together a warm run costs process start-up.

Verified: two consecutive runs over examples/ produce byte-identical stdout (elapsed line excluded), 79 files / 26 with errors / 38 errors on both. Both test lanes 291 + 1 expected fail (the tests drive validateFile directly, so they are unaffected by design).

Measured: example app (838 files) warm run 3.3 s → 0.3 s; bench warm run −48 %, one cached file −32 %.

Same cross-file caveat as the other caches: a consumer's report keys on the consumer's content, so a change in an imported component's template is not seen until the consumer changes or the plugin version does. Independent of #54 and #55 in code (touches run.ts and appends to lib/cache.ts).

Cowritten by Claude

@johanrd johanrd added enhancement New feature or request run-bench Run the benchmark comparison on this pull request labels Aug 29, 2026
@johanrd
johanrd requested a balanced review from Copilot August 29, 2026 09:15
@github-actions

github-actions Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

🏎️ Benchmark Comparison

Benchmark Control (p50) Experiment (p50) Δ
extract small template 822.94 µs 792.20 µs -3.7%
extract medium template 3.26 ms 3.32 ms +1.6%
extract cross-file resolution 2.95 ms 3.00 ms +1.5%
extract large template 700.60 µs 709.55 µs +1.3%
cold run (cache off) 6425.80 ms 6379.52 ms -0.7%
🟢 warm run (all cached) 4676.21 ms 879.56 ms -81.2%
🟢 one cached file 451.81 ms 332.34 ms -26.4%
no glint 4948.58 ms 4915.37 ms -0.7%

🟢 faster · 🔴 slower · 🟡 5–10 %, possibly noise · ⚪ within 5 %

Full output
clk: ~3.05 GHz
cpu: AMD EPYC 7763 64-Core Processor
runtime: node 24.19.0 (x64-linux)

benchmark                    avg (min … max) p75 / p99    (min … top 1%)
-------------------------------------------- -------------------------------
extract small template          1.17 ms/iter   1.15 ms  █                   
                       (633.07 µs … 5.85 ms)   4.01 ms ▆█▂                  
                     (  3.77 kb …   3.89 mb) 305.44 kb ███▅▄▃▃▁▂▂▁▂▁▂▂▂▂▁▁▂▁

extract medium template         3.90 ms/iter   4.32 ms  █                   
                        (2.76 ms … 11.42 ms)   9.05 ms ▃█▃                  
                     ( 21.97 kb …   4.30 mb) 771.08 kb ███▆▄▆▃▂▃▃▃▂▂▁▁▁▁▁▁▂▁

extract cross-file resolution   3.26 ms/iter   3.35 ms   █▂                 
                         (2.49 ms … 7.80 ms)   6.24 ms ▂▇██                 
                     ( 31.48 kb …   1.48 mb) 424.49 kb ████▆▆▅▃▃▃▁▁▂▃▂▂▁▁▂▁▁

extract large template        739.23 µs/iter 756.14 µs  █▃                  
                       (601.03 µs … 3.20 ms)   1.90 ms  ██▂                 
                     ( 10.93 kb …   1.89 mb)  52.68 kb ▇███▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

whole process (min / p50 of 3 runs, 21 files)
  cold run (cache off)           6365 ms /   6426 ms
  warm run (all cached)          4553 ms /   4676 ms
  one cached file                 452 ms /    452 ms
  no glint                       4900 ms /   4949 ms
clk: ~3.11 GHz
cpu: AMD EPYC 7763 64-Core Processor
runtime: node 24.19.0 (x64-linux)

benchmark                    avg (min … max) p75 / p99    (min … top 1%)
-------------------------------------------- -------------------------------
extract small template          1.14 ms/iter   1.15 ms  █                   
                       (635.68 µs … 5.83 ms)   4.12 ms ██                   
                     (  6.22 kb …   3.53 mb) 309.09 kb ███▇▂▃▂▂▁▂▂▁▁▂▂▂▂▁▁▁▁

extract medium template         3.93 ms/iter   3.93 ms  █                   
                        (2.74 ms … 10.07 ms)   9.46 ms ▂██                  
                     ( 56.46 kb …   4.11 mb) 761.16 kb ████▄▃▃▂▂▃▃▂▂▁▁▁▁▁▂▁▁

extract cross-file resolution   3.36 ms/iter   3.49 ms ▄▇█                  
                         (2.51 ms … 8.69 ms)   7.81 ms ███▃                 
                     (  2.73 kb …   1.43 mb) 420.73 kb ████▇▅▄▄▃▂▃▃▃▂▂▂▂▁▁▁▂

extract large template        792.19 µs/iter 763.11 µs ▃█                   
                       (611.78 µs … 6.28 ms)   3.31 ms ██                   
                     (  4.21 kb …   1.99 mb)  50.63 kb ██▃▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

whole process (min / p50 of 3 runs, 21 files)
  cold run (cache off)           6317 ms /   6380 ms
  warm run (all cached)           873 ms /    880 ms
  one cached file                 331 ms /    332 ms
  no glint                       4905 ms /   4915 ms

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It introduces a correctness-sensitive caching layer that can silently replay stale validation reports, and the new cache read/write paths have no direct test coverage despite the sibling cache being thoroughly tested.

Pull request overview

This PR adds a CLI-level report cache to validate-gts. On each run it caches every file's deduplicated html-validate report on disk under node_modules/.cache/html-validate-ember/report/, keyed by the file's content, the resolved .htmlvalidate.json config, html-validate's version, the tsconfig (via Glint), and the HVE_* environment switches. On a cache hit the file is not re-validated; the stored report feeds the same counters and formatter output. It is the CLI counterpart of the transform cache (#55) and reuses the same invalidation machinery (PLUGIN_VERSION, PLUGIN_SOURCE_SHA, HVE_NO_CACHE=1 bypass).

Changes:

  • Adds a report disk cache (reportCacheKey, readReportCache, writeReportCache, CachedReport) to lib/cache.ts, mirroring the existing per-path glint/transform cache pattern.
  • Refactors the per-file loop in run.ts to a shared recordReport helper and consults/writes the report cache around validateFile, keeping counters and formatter output identical on hits and misses.
File summaries
File Description
lib/cache.ts Appends the report cache: key derivation and path-keyed read/write with PLUGIN_VERSION/PLUGIN_SOURCE_SHA staleness checks.
run.ts Computes a per-file report key, replays cached reports through a new recordReport helper, and writes reports on misses.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread lib/cache.ts
`validate-gts` caches each file's deduplicated html-validate report,
keyed by the file's content, the resolved configuration, html-validate's
version, the tsconfig and the environment switches (under
`.../html-validate-ember/report/`). An unchanged file is not validated
again; its report is replayed into the same counters and output.

Console app (838 files), warm run: 3.3 s -> 0.3 s. Output identical to
an uncached run; `HVE_NO_CACHE=1` bypasses it like the other caches.

Cowritten by Claude
The key carries the backend kind from `backendKindFor` (as the transform
cache does since #55) instead of the raw `HVE_TS_BACKEND`. Round-trip,
miss-on-any-input-change and one-entry-per-path tests.

Cowritten by Claude
@johanrd
johanrd force-pushed the perf-report-cache branch from e5b5e7b to c16edf4 Compare August 29, 2026 09:27
@johanrd
johanrd merged commit 7af175e into main Aug 29, 2026
4 checks passed
@github-actions github-actions Bot mentioned this pull request Aug 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request run-bench Run the benchmark comparison on this pull request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants