Skip unnecessary submodule updates during hook repo clone#2255
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #2255 +/- ##
==========================================
+ Coverage 92.90% 93.00% +0.10%
==========================================
Files 127 127
Lines 27583 27674 +91
==========================================
+ Hits 25625 25739 +114
+ Misses 1958 1935 -23 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
📦 Cargo Bloat ComparisonBinary size change: +0.00% (26.8 MiB → 26.8 MiB) Expand for cargo-bloat outputHead Branch ResultsBase Branch Results |
⚡️ Hyperfine BenchmarksSummary: 0 regressions, 0 improvements above the 10% threshold. Environment
CLI CommandsBenchmarking basic commands in the main repo:
|
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base --version |
2.2 ± 0.1 | 2.0 | 2.6 | 1.00 |
prek-head --version |
2.2 ± 0.2 | 2.0 | 3.1 | 1.01 ± 0.08 |
prek list
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base list |
9.0 ± 0.1 | 8.8 | 9.5 | 1.00 |
prek-head list |
9.3 ± 0.4 | 8.9 | 12.8 | 1.03 ± 0.05 |
prek validate-config .pre-commit-config.yaml
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base validate-config .pre-commit-config.yaml |
3.0 ± 0.1 | 2.9 | 3.1 | 1.00 |
prek-head validate-config .pre-commit-config.yaml |
3.0 ± 0.1 | 2.9 | 3.9 | 1.01 ± 0.05 |
prek sample-config
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base sample-config |
2.4 ± 0.1 | 2.3 | 2.5 | 1.00 |
prek-head sample-config |
2.4 ± 0.1 | 2.3 | 2.8 | 1.00 ± 0.04 |
Cold vs Warm Runs
Comparing first run (cold) vs subsequent runs (warm cache):
prek run --all-files (cold - no cache)
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base run --all-files |
75.5 ± 2.9 | 71.8 | 79.5 | 1.00 |
prek-head run --all-files |
78.7 ± 3.2 | 73.6 | 84.9 | 1.04 ± 0.06 |
prek run --all-files (warm - with cache)
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base run --all-files |
74.9 ± 2.4 | 71.0 | 80.0 | 1.00 |
prek-head run --all-files |
75.4 ± 2.7 | 71.8 | 79.8 | 1.01 ± 0.05 |
Full Hook Suite
Running the builtin hook suite on the benchmark workspace:
prek run --all-files (full builtin hook suite)
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base run --all-files |
75.4 ± 2.4 | 70.5 | 80.5 | 1.01 ± 0.06 |
prek-head run --all-files |
75.0 ± 3.6 | 69.9 | 91.7 | 1.00 |
Individual Hook Performance
Benchmarking each hook individually on the test repo:
prek run trailing-whitespace --all-files
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base run trailing-whitespace --all-files |
20.4 ± 0.3 | 19.8 | 20.9 | 1.03 ± 0.02 |
prek-head run trailing-whitespace --all-files |
19.9 ± 0.3 | 19.3 | 20.5 | 1.00 |
prek run end-of-file-fixer --all-files
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base run end-of-file-fixer --all-files |
26.3 ± 1.8 | 24.1 | 31.9 | 1.00 |
prek-head run end-of-file-fixer --all-files |
26.3 ± 1.9 | 23.7 | 30.6 | 1.00 ± 0.10 |
prek run check-json --all-files
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base run check-json --all-files |
7.6 ± 0.4 | 7.1 | 8.6 | 1.01 ± 0.06 |
prek-head run check-json --all-files |
7.5 ± 0.3 | 7.2 | 8.0 | 1.00 |
prek run check-yaml --all-files
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base run check-yaml --all-files |
7.3 ± 0.1 | 7.1 | 7.7 | 1.00 |
prek-head run check-yaml --all-files |
7.3 ± 0.1 | 7.1 | 7.6 | 1.00 ± 0.02 |
prek run check-toml --all-files
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base run check-toml --all-files |
7.4 ± 0.2 | 6.9 | 7.8 | 1.00 ± 0.04 |
prek-head run check-toml --all-files |
7.3 ± 0.2 | 6.9 | 7.8 | 1.00 |
prek run check-xml --all-files
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base run check-xml --all-files |
7.5 ± 0.3 | 7.1 | 8.1 | 1.01 ± 0.06 |
prek-head run check-xml --all-files |
7.4 ± 0.4 | 7.0 | 8.8 | 1.00 |
prek run detect-private-key --all-files
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base run detect-private-key --all-files |
13.6 ± 1.2 | 11.7 | 15.6 | 1.00 |
prek-head run detect-private-key --all-files |
13.7 ± 1.2 | 11.9 | 16.8 | 1.01 ± 0.13 |
prek run fix-byte-order-marker --all-files
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base run fix-byte-order-marker --all-files |
17.8 ± 0.9 | 16.5 | 20.0 | 1.00 |
prek-head run fix-byte-order-marker --all-files |
17.8 ± 0.8 | 16.7 | 20.0 | 1.00 ± 0.06 |
Installation Performance
Benchmarking hook installation (fast path hooks skip Python setup):
prek install-hooks (cold - no cache)
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base install-hooks |
4.4 ± 0.1 | 4.3 | 4.5 | 1.00 |
prek-head install-hooks |
4.4 ± 0.1 | 4.3 | 4.4 | 1.00 ± 0.02 |
prek install-hooks (warm - with cache)
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base install-hooks |
4.4 ± 0.1 | 4.3 | 4.6 | 1.00 |
prek-head install-hooks |
4.4 ± 0.0 | 4.4 | 4.5 | 1.01 ± 0.03 |
File Filtering/Scoping Performance
Testing different file selection modes:
prek run (staged files only)
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base run |
37.8 ± 1.1 | 36.2 | 40.4 | 1.01 ± 0.04 |
prek-head run |
37.6 ± 0.8 | 36.2 | 39.1 | 1.00 |
prek run --files '*.json' (specific file type)
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base run --files '*.json' |
7.8 ± 0.1 | 7.6 | 8.0 | 1.00 ± 0.01 |
prek-head run --files '*.json' |
7.7 ± 0.1 | 7.6 | 7.9 | 1.00 |
Workspace Discovery & Initialization
Benchmarking hook discovery and initialization overhead:
prek run --dry-run --all-files (measures init overhead)
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base run --dry-run --all-files |
6.6 ± 0.1 | 6.5 | 7.0 | 1.00 |
prek-head run --dry-run --all-files |
6.7 ± 0.1 | 6.5 | 6.9 | 1.01 ± 0.03 |
Meta Hooks Performance
Benchmarking meta hooks separately:
prek run check-hooks-apply --all-files
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base run check-hooks-apply --all-files |
11.7 ± 0.1 | 11.5 | 12.0 | 1.00 |
prek-head run check-hooks-apply --all-files |
11.7 ± 0.1 | 11.6 | 11.9 | 1.00 ± 0.02 |
prek run check-useless-excludes --all-files
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base run check-useless-excludes --all-files |
11.9 ± 0.5 | 11.6 | 13.5 | 1.09 ± 0.13 |
prek-head run check-useless-excludes --all-files |
10.9 ± 1.3 | 10.3 | 15.2 | 1.00 |
prek run identity --all-files
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
prek-base run identity --all-files |
9.6 ± 0.1 | 9.5 | 9.9 | 1.00 |
prek-head run identity --all-files |
9.7 ± 0.1 | 9.5 | 9.9 | 1.00 ± 0.02 |
fbcb9af to
99aae19
Compare
…e-skip # Conflicts: # crates/prek/src/git.rs
|
Thank you, a very good improvement! |
Summary
Skip
git submodule update --init --recursiveafter cloning a hook repo when the checked-out repo has neither.gitmodulesnor gitlink entries.Most hook repositories do not use submodules. Before this change,
prekstill rangit submodule updatefor every cloned remote repo, which adds an avoidable Git subprocess on cold cache paths.The new behavior keeps the existing submodule path when either:
.gitmodulesexists160000entries)That preserves behavior for normal submodule repos, broken
.gitmodulescases, and gitlink-without-.gitmodulesedge cases.Benchmarks
Benchmarked cold
prek listwith fresh isolatedPREK_HOMEagainst local mirrors of real hook repositories to avoid network variance. Baseline wasupstream/master; changed was this branch. Each scenario used 40 runs and 6 warmups.pre-commit/pre-commit-hooksv6.0.0132.3 ± 12.6 ms84.5 ± 11.0 ms1.57x fasterastral-sh/ruff-pre-commitv0.9.9113.4 ± 14.2 ms76.8 ± 7.1 ms1.48x fasterpsf/black25.1.0274.7 ± 24.9 ms231.6 ± 18.9 ms1.19x fasterAll benchmarked repos had no
.gitmodulesand no gitlinks. Trace logs confirmed the old path ran:The new path checked gitlinks with:
and skipped submodule update.