Skip to content

feat(perf): cache per-module builds and honor --rebuild/--ignore-cache#1004

Merged
xieofxie merged 2 commits into
mainfrom
hualxie/module_use_cache
Jul 1, 2026
Merged

feat(perf): cache per-module builds and honor --rebuild/--ignore-cache#1004
xieofxie merged 2 commits into
mainfrom
hualxie/module_use_cache

Conversation

@xieofxie

Copy link
Copy Markdown
Contributor

Summary

winml perf --module built every submodule into a throwaway tempfile.TemporaryDirectory with no cache_key and no rebuild flag, so per-module artifacts were rebuilt on every run and --rebuild / --ignore-cache were silently ignored. The single-model path already honored these flags via WinMLAutoModelauto.py.

This mirrors auto.py's cache logic in _perf_modules:

  • Default: each submodule builds into the model's persistent cache dir (~/.cache/winml/artifacts/<model_slug>/) and is reused on the next run.
  • --rebuild: reuses the cache dir but overwrites artifacts.
  • --ignore-cache: falls back to a temp dir + forced rebuild (prior behavior, now opt-in).

Why per-module caching is collision-free

Each submodule config carries a unique loader.module_path (plus its traced I/O shapes). cfg.generate_cache_key() hashes the full config, so every instance gets a distinct key — even shape-identical siblings — and build_hf_model's cache_key filename prefixing keeps each instance's model.onnx separate within one shared model dir.

Behavior change worth noting

Per-module artifacts now persist by default (more disk use), which is the intended consequence of matching the single-model / auto.py behavior.

Tests

Added TestPerfModuleCache (default → persistent dir + rebuild=False; --rebuildrebuild=True in cache dir; --ignore-cache → temp dir + rebuild=True). Full tests/unit/commands/test_perf_module.py: 15 passed.

Closes #918

🤖 Generated with Claude Code

Per-module benchmarking built every submodule into a throwaway
tempfile.TemporaryDirectory with no cache_key and no rebuild flag, so
artifacts were rebuilt on every run and --rebuild/--ignore-cache were
silently ignored. The single-model path already honored these flags via
WinMLAutoModel.

Mirror auto.py's cache logic in _perf_modules: build into the model's
persistent cache dir keyed per submodule (cfg.generate_cache_key() folds
in loader.module_path and traced I/O shapes, so sibling instances get
distinct keys and coexist in one model dir), and forward rebuild. With
--ignore-cache, fall back to a temp dir + forced rebuild.

Closes #918
@xieofxie xieofxie requested a review from a team as a code owner June 30, 2026 07:24

@DingmaomaoBJTU DingmaomaoBJTU left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed the per-module cache changes. The logic cleanly mirrors auto.py/the single-model path (use_cache = not ignore_cache, force_rebuild = rebuild or ignore_cache, persistent model dir + per-module cache_key, temp-dir fallback on --ignore-cache), and build_hf_model creates output_dir and scopes its rebuild-glob to {cache_key}_*.onnx, so sibling modules coexist and --rebuild won't wipe each other's artifacts. Ran tests/unit/commands/test_perf_module.py locally: 15 passed. Two notes inline — one behavioral nuance and one optional test-coverage suggestion; neither is blocking.

Comment thread src/winml/modelkit/commands/perf.py Outdated
Comment thread tests/unit/commands/test_perf_module.py
…mize isn't ignored

skip_optimize / hack_max_optim_iterations are build_hf_model kwargs, not
part of WinMLBuildConfig, so generate_cache_key() didn't reflect them.
After a cached build, re-running with --no-optimize / --no-analyze /
--max-optim-iterations silently reused the cached artifact in both the
single-model (auto.py) and per-module (perf.py) paths.

get_cache_key() now folds recognized build-control overrides into the
key. Default builds keep their existing key (backward compatible); only
non-default toggles get a distinct suffix. Applied at every call site
(auto.py HF + ONNX, perf module, build single-model).

@DingmaomaoBJTU DingmaomaoBJTU left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Re-reviewed the new commit (53a8f26) — it directly resolves both points from my previous review:

  1. Optimize/analyze toggles now affect the cache key. get_cache_key folds skip_optimize / hack_max_optim_iterations in, applied at all four call sites (auto.py HF + ONNX, perf module, build single-model). I checked key/build consistency: the same controls folded into the key are exactly what reach build_hf_model / build_onnx_model, so a later --no-optimize run no longer silently reuses an optimized artifact. Nice that path.py's stdlib-only / zero-internal-imports contract is preserved (hashlib/json/typing are all stdlib).
  2. Collision-free claim now has a real test. test_sibling_instances_get_distinct_cache_keys uses two distinct config hashes (no longer mocked to a constant) and asserts distinct cache_keys reach build_hf_model; test_no_optimize_changes_cache_key guards the flag→key coupling.

Verified locally: applied the PR head and ran tests/unit/cache/test_path.py + tests/unit/commands/test_perf_module.py33 passed. One optional, non-blocking note inline. LGTM otherwise.

Comment thread src/winml/modelkit/cache/path.py

@DingmaomaoBJTU DingmaomaoBJTU left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approving. The follow-up commit cleanly resolves both points from my earlier reviews: optimize/analyze toggles now fold into the cache key at all four call sites (verified key/build consistency), and the collision-free claim has real test coverage. Verified locally — tests/unit/cache/test_path.py + tests/unit/commands/test_perf_module.py: 33 passed. The two inline notes are minor/optional and not blocking.

@xieofxie xieofxie merged commit 8ad3b67 into main Jul 1, 2026
9 checks passed
@xieofxie xieofxie deleted the hualxie/module_use_cache branch July 1, 2026 09:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: perf --module should also use cache folder instead of temp dir

2 participants