Summary
I’ve just taken prek for a spin and while the hook installation was faster (maybe 3-4x!), meaning overall run the first time (after wiping the cache dirs for level playing field) was faster, subsequent runs were slower (by about 0.5s - 1s) because somehow prek is slower to execute the hooks than pre-commit.
I presume this is worth a bug report given speed is prek’s primary goal, and hooks are likely going to be executed more often than they are installed (at least locally)
Platform
Linux 5.15.0-125-generic x86_64 GNU/Linux
Version
prek 0.2.5
.pre-commit-config.yaml
Click to show
ci:
autofix_commit_msg: "chore(pre-commit): autofix run"
autoupdate_commit_msg: "chore(pre-commit): autoupdate hooks"
default_install_hook_types:
- pre-commit
- commit-msg
repos:
- repo: https://github.com/compilerla/conventional-pre-commit
rev: v4.2.0
hooks:
- id: conventional-pre-commit
stages: [commit-msg]
# args: [build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: check-toml
- id: check-yaml
exclude: ^mkdocs.yml
- id: debug-statements
- id: end-of-file-fixer
- id: name-tests-test
- id: trailing-whitespace
- repo: https://github.com/pappasam/toml-sort
rev: v0.24.3
hooks:
- id: toml-sort-fix
- repo: https://github.com/asottile/add-trailing-comma
rev: v3.2.0
hooks:
- id: add-trailing-comma
- repo: https://github.com/asottile/pyupgrade
rev: v3.20.0
hooks:
- id: pyupgrade
args: [--py310-plus]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.13.3
hooks:
# Run the linter
- id: ruff
args: [--fix]
# Run the formatter
- id: ruff-format
Log file
Click to show
2025-10-13T09:32:47.825851Z DEBUG prek: 0.2.5 (/home/louis/.local/bin/prek)
2025-10-13T09:32:48.062549Z DEBUG Git root: /home/louis/tmp/polars-permute-plugin
2025-10-13T09:32:48.062881Z DEBUG Found workspace root at `/home/louis/tmp/polars-permute-plugin`
2025-10-13T09:32:48.063043Z TRACE Include selectors:
2025-10-13T09:32:48.063131Z TRACE Skip selectors:
2025-10-13T09:32:48.102301Z DEBUG discover{store=Store { path: "/home/louis/.cache/prek" }
root="/home/louis/tmp/polars-permute-plugin" config=None refresh=false}: Loaded workspace from cache
2025-10-13T09:32:48.103186Z DEBUG discover{store=Store { path: "/home/louis/.cache/prek" }
root="/home/louis/tmp/polars-permute-plugin" config=None refresh=false}: Loading project
configuration path=.pre-commit-config.yaml
2025-10-13T09:32:48.107267Z TRACE discover{store=Store { path: "/home/louis/.cache/prek" }
root="/home/louis/tmp/polars-permute-plugin" config=None refresh=false}: close time.busy=43.7ms
time.idle=178µs
2025-10-13T09:32:48.108815Z TRACE Checking lock resource="store" path=/home/louis/.cache/prek/.lock
2025-10-13T09:32:48.108979Z DEBUG Acquired lock resource="store"
2025-10-13T09:32:48.124538Z DEBUG Hooks going to run: ["check-toml", "check-yaml",
"debug-statements", "end-of-file-fixer", "name-tests-test", "trailing-whitespace", "toml-sort-fix",
"add-trailing-comma", "pyupgrade", "ruff", "ruff-format"]
2025-10-13T09:32:48.125403Z DEBUG Checking health of installed hooks
2025-10-13T09:32:48.128111Z TRACE Executing
`/home/louis/.cache/prek/hooks/python-vtizewRRafdh8DCZpy67/bin/python -I -c import sys
print(f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}")
print(sys.base_exec_prefix)
[...]`
2025-10-13T09:32:48.154296Z TRACE Executing
`/home/louis/.cache/prek/hooks/python-pnR5Fl7LBdVfGJ6wApBn/bin/python -I -c import sys
print(f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}")
print(sys.base_exec_prefix)
[...]`
2025-10-13T09:32:48.154920Z TRACE Executing
`/home/louis/.cache/prek/hooks/python-lcxTSDMCHRxaiQJWjWsF/bin/python -I -c import sys
print(f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}")
print(sys.base_exec_prefix)
[...]`
2025-10-13T09:32:48.155404Z TRACE Executing
`/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE/bin/python -I -c import sys
print(f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}")
print(sys.base_exec_prefix)
[...]`
2025-10-13T09:32:48.232883Z TRACE Executing
`/home/louis/.cache/prek/hooks/python-mkiKwZtEtSB2XIgOma4s/bin/python -I -c import sys
print(f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}")
print(sys.base_exec_prefix)
[...]`
2025-10-13T09:32:48.256576Z DEBUG Found installed environment for hook `check-toml` at
`/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE`
2025-10-13T09:32:48.267917Z DEBUG Found installed environment for hook `check-yaml` at
`/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE`
2025-10-13T09:32:48.268083Z DEBUG Found installed environment for hook `debug-statements` at
`/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE`
2025-10-13T09:32:48.268180Z DEBUG Found installed environment for hook `end-of-file-fixer` at
`/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE`
2025-10-13T09:32:48.268326Z DEBUG Found installed environment for hook `name-tests-test` at
`/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE`
2025-10-13T09:32:48.268501Z DEBUG Found installed environment for hook `trailing-whitespace` at
`/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE`
2025-10-13T09:32:48.268649Z DEBUG Found installed environment for hook `toml-sort-fix` at
`/home/louis/.cache/prek/hooks/python-vtizewRRafdh8DCZpy67`
2025-10-13T09:32:48.268762Z DEBUG Found installed environment for hook `add-trailing-comma` at
`/home/louis/.cache/prek/hooks/python-pnR5Fl7LBdVfGJ6wApBn`
2025-10-13T09:32:48.269042Z DEBUG Found installed environment for hook `pyupgrade` at
`/home/louis/.cache/prek/hooks/python-mkiKwZtEtSB2XIgOma4s`
2025-10-13T09:32:48.269396Z DEBUG Found installed environment for hook `ruff` at
`/home/louis/.cache/prek/hooks/python-lcxTSDMCHRxaiQJWjWsF`
2025-10-13T09:32:48.269682Z DEBUG Found installed environment for hook `ruff-format` at
`/home/louis/.cache/prek/hooks/python-lcxTSDMCHRxaiQJWjWsF`
2025-10-13T09:32:48.269916Z TRACE Released lock path=/home/louis/.cache/prek/.lock
2025-10-13T09:32:48.270180Z TRACE Executing `cd /home/louis/tmp/polars-permute-plugin &&
/usr/bin/git ls-files -z -- /home/louis/tmp/polars-permute-plugin`
2025-10-13T09:32:48.273014Z DEBUG All files in the workspace: 18
2025-10-13T09:32:48.273416Z TRACE Executing `/usr/bin/git diff --
/home/louis/tmp/polars-permute-plugin`
2025-10-13T09:32:48.276875Z TRACE Files for project `.` after filtered: 18
2025-10-13T09:32:48.277116Z TRACE Files for hook `check-toml` after filtered: 1
2025-10-13T09:32:48.277224Z DEBUG Running builtin hook: check-toml
2025-10-13T09:32:48.277392Z TRACE Executing `/usr/bin/git diff --
/home/louis/tmp/polars-permute-plugin`
2025-10-13T09:32:48.281031Z TRACE Files for hook `check-yaml` after filtered: 1
2025-10-13T09:32:48.281122Z DEBUG Running builtin hook: check-yaml
2025-10-13T09:32:48.281155Z TRACE Resolved command: check-yaml
2025-10-13T09:32:48.281604Z TRACE Executing `/usr/bin/git diff --
/home/louis/tmp/polars-permute-plugin`
2025-10-13T09:32:48.284745Z TRACE Files for hook `debug-statements` after filtered: 11
2025-10-13T09:32:48.284910Z TRACE Resolved command:
/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE/bin/debug-statement-hook
2025-10-13T09:32:48.285013Z TRACE Found shebang:
["/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE/bin/python3"]
2025-10-13T09:32:48.285126Z TRACE Resolved interpreter:
/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE/bin/python3
2025-10-13T09:32:48.285182Z TRACE Running debug-statements total_files=11 concurrency=4
2025-10-13T09:32:48.285396Z TRACE Executing `cd /home/louis/tmp/polars-permute-plugin &&
/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE/bin/python3
/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE/bin/debug-statement-hook
tests/basic_permutations_test.py [...]`
2025-10-13T09:32:48.286780Z TRACE Executing `cd /home/louis/tmp/polars-permute-plugin &&
/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE/bin/python3
/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE/bin/debug-statement-hook
tests/expressions_test.py [...]`
2025-10-13T09:32:48.290000Z TRACE Executing `cd /home/louis/tmp/polars-permute-plugin &&
/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE/bin/python3
/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE/bin/debug-statement-hook
tests/data_integrity_test.py [...]`
2025-10-13T09:32:48.800182Z TRACE Executing `/usr/bin/git diff --
/home/louis/tmp/polars-permute-plugin`
2025-10-13T09:32:48.803527Z TRACE Files for hook `end-of-file-fixer` after filtered: 18
2025-10-13T09:32:48.803605Z DEBUG Running builtin hook: end-of-file-fixer
2025-10-13T09:32:48.805570Z TRACE Executing `/usr/bin/git diff --
/home/louis/tmp/polars-permute-plugin`
2025-10-13T09:32:48.816701Z TRACE Files for hook `name-tests-test` after filtered: 10
2025-10-13T09:32:48.816835Z TRACE Resolved command:
/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE/bin/name-tests-test
2025-10-13T09:32:48.816888Z TRACE Found shebang:
["/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE/bin/python3"]
2025-10-13T09:32:48.816965Z TRACE Resolved interpreter:
/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE/bin/python3
2025-10-13T09:32:48.816997Z TRACE Running name-tests-test total_files=10 concurrency=4
2025-10-13T09:32:48.817142Z TRACE Executing `cd /home/louis/tmp/polars-permute-plugin &&
/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE/bin/python3
/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE/bin/name-tests-test
tests/before_after_test.py [...]`
2025-10-13T09:32:48.819924Z TRACE Executing `cd /home/louis/tmp/polars-permute-plugin &&
/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE/bin/python3
/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE/bin/name-tests-test
tests/multiple_columns_test.py [...]`
2025-10-13T09:32:48.821127Z TRACE Executing `cd /home/louis/tmp/polars-permute-plugin &&
/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE/bin/python3
/home/louis/.cache/prek/hooks/python-sNi6mT5pdthxSLXBnboE/bin/name-tests-test
tests/edge_cases_test.py [...]`
2025-10-13T09:32:49.261008Z TRACE Executing `/usr/bin/git diff --
/home/louis/tmp/polars-permute-plugin`
2025-10-13T09:32:49.264338Z TRACE Files for hook `trailing-whitespace` after filtered: 18
2025-10-13T09:32:49.264404Z DEBUG Running builtin hook: trailing-whitespace
2025-10-13T09:32:49.264442Z TRACE Resolved command: trailing-whitespace-fixer
2025-10-13T09:32:49.266841Z TRACE Executing `/usr/bin/git diff --
/home/louis/tmp/polars-permute-plugin`
2025-10-13T09:32:49.270750Z TRACE Files for hook `toml-sort-fix` after filtered: 1
2025-10-13T09:32:49.271250Z TRACE Resolved command:
/home/louis/.cache/prek/hooks/python-vtizewRRafdh8DCZpy67/bin/toml-sort
2025-10-13T09:32:49.271451Z TRACE Found shebang:
["/home/louis/.cache/prek/hooks/python-vtizewRRafdh8DCZpy67/bin/python3"]
2025-10-13T09:32:49.271779Z TRACE Resolved interpreter:
/home/louis/.cache/prek/hooks/python-vtizewRRafdh8DCZpy67/bin/python3
2025-10-13T09:32:49.271899Z TRACE Running toml-sort-fix total_files=1 concurrency=4
2025-10-13T09:32:49.272432Z TRACE Executing `cd /home/louis/tmp/polars-permute-plugin &&
/home/louis/.cache/prek/hooks/python-vtizewRRafdh8DCZpy67/bin/python3
/home/louis/.cache/prek/hooks/python-vtizewRRafdh8DCZpy67/bin/toml-sort --in-place pyproject.toml`
2025-10-13T09:32:49.520589Z TRACE Executing `/usr/bin/git diff --
/home/louis/tmp/polars-permute-plugin`
2025-10-13T09:32:49.523985Z TRACE Files for hook `add-trailing-comma` after filtered: 11
2025-10-13T09:32:49.524119Z TRACE Resolved command:
/home/louis/.cache/prek/hooks/python-pnR5Fl7LBdVfGJ6wApBn/bin/add-trailing-comma
2025-10-13T09:32:49.524174Z TRACE Found shebang:
["/home/louis/.cache/prek/hooks/python-pnR5Fl7LBdVfGJ6wApBn/bin/python3"]
2025-10-13T09:32:49.524253Z TRACE Resolved interpreter:
/home/louis/.cache/prek/hooks/python-pnR5Fl7LBdVfGJ6wApBn/bin/python3
2025-10-13T09:32:49.524286Z TRACE Running add-trailing-comma total_files=11 concurrency=4
2025-10-13T09:32:49.524437Z TRACE Executing `cd /home/louis/tmp/polars-permute-plugin &&
/home/louis/.cache/prek/hooks/python-pnR5Fl7LBdVfGJ6wApBn/bin/python3
/home/louis/.cache/prek/hooks/python-pnR5Fl7LBdVfGJ6wApBn/bin/add-trailing-comma
tests/basic_permutations_test.py [...]`
2025-10-13T09:32:49.525769Z TRACE Executing `cd /home/louis/tmp/polars-permute-plugin &&
/home/louis/.cache/prek/hooks/python-pnR5Fl7LBdVfGJ6wApBn/bin/python3
/home/louis/.cache/prek/hooks/python-pnR5Fl7LBdVfGJ6wApBn/bin/add-trailing-comma
tests/expressions_test.py [...]`
2025-10-13T09:32:49.527143Z TRACE Executing `cd /home/louis/tmp/polars-permute-plugin &&
/home/louis/.cache/prek/hooks/python-pnR5Fl7LBdVfGJ6wApBn/bin/python3
/home/louis/.cache/prek/hooks/python-pnR5Fl7LBdVfGJ6wApBn/bin/add-trailing-comma
tests/data_integrity_test.py [...]`
2025-10-13T09:32:50.122101Z TRACE Executing `/usr/bin/git diff --
/home/louis/tmp/polars-permute-plugin`
2025-10-13T09:32:50.125387Z TRACE Files for hook `pyupgrade` after filtered: 11
2025-10-13T09:32:50.125532Z TRACE Resolved command:
/home/louis/.cache/prek/hooks/python-mkiKwZtEtSB2XIgOma4s/bin/pyupgrade
2025-10-13T09:32:50.125594Z TRACE Found shebang:
["/home/louis/.cache/prek/hooks/python-mkiKwZtEtSB2XIgOma4s/bin/python3"]
2025-10-13T09:32:50.125671Z TRACE Resolved interpreter:
/home/louis/.cache/prek/hooks/python-mkiKwZtEtSB2XIgOma4s/bin/python3
2025-10-13T09:32:50.125703Z TRACE Running pyupgrade total_files=11 concurrency=4
2025-10-13T09:32:50.125849Z TRACE Executing `cd /home/louis/tmp/polars-permute-plugin &&
/home/louis/.cache/prek/hooks/python-mkiKwZtEtSB2XIgOma4s/bin/python3
/home/louis/.cache/prek/hooks/python-mkiKwZtEtSB2XIgOma4s/bin/pyupgrade --py310-plus
tests/basic_permutations_test.py [...]`
2025-10-13T09:32:50.127313Z TRACE Executing `cd /home/louis/tmp/polars-permute-plugin &&
/home/louis/.cache/prek/hooks/python-mkiKwZtEtSB2XIgOma4s/bin/python3
/home/louis/.cache/prek/hooks/python-mkiKwZtEtSB2XIgOma4s/bin/pyupgrade --py310-plus
tests/expressions_test.py [...]`
2025-10-13T09:32:50.128777Z TRACE Executing `cd /home/louis/tmp/polars-permute-plugin &&
/home/louis/.cache/prek/hooks/python-mkiKwZtEtSB2XIgOma4s/bin/python3
/home/louis/.cache/prek/hooks/python-mkiKwZtEtSB2XIgOma4s/bin/pyupgrade --py310-plus
tests/data_integrity_test.py [...]`
2025-10-13T09:32:51.004579Z TRACE Executing `/usr/bin/git diff --
/home/louis/tmp/polars-permute-plugin`
2025-10-13T09:32:51.007888Z TRACE Files for hook `ruff` after filtered: 11
2025-10-13T09:32:51.008015Z TRACE Resolved command:
/home/louis/.cache/prek/hooks/python-lcxTSDMCHRxaiQJWjWsF/bin/ruff
2025-10-13T09:32:51.008081Z TRACE Running ruff total_files=11 concurrency=1
2025-10-13T09:32:51.008218Z TRACE Executing `cd /home/louis/tmp/polars-permute-plugin &&
/home/louis/.cache/prek/hooks/python-lcxTSDMCHRxaiQJWjWsF/bin/ruff check --force-exclude --fix
tests/basic_permutations_test.py tests/shift_operations_test.py tests/conftest.py [...]`
2025-10-13T09:32:51.369452Z TRACE Executing `/usr/bin/git diff --
/home/louis/tmp/polars-permute-plugin`
2025-10-13T09:32:51.373068Z TRACE Files for hook `ruff-format` after filtered: 11
2025-10-13T09:32:51.373201Z TRACE Resolved command:
/home/louis/.cache/prek/hooks/python-lcxTSDMCHRxaiQJWjWsF/bin/ruff
2025-10-13T09:32:51.373275Z TRACE Running ruff-format total_files=11 concurrency=1
2025-10-13T09:32:51.373420Z TRACE Executing `cd /home/louis/tmp/polars-permute-plugin &&
/home/louis/.cache/prek/hooks/python-lcxTSDMCHRxaiQJWjWsF/bin/ruff format --force-exclude
tests/basic_permutations_test.py tests/shift_operations_test.py tests/conftest.py [...]`
2025-10-13T09:32:51.386119Z TRACE Executing `/usr/bin/git diff --
/home/louis/tmp/polars-permute-plugin`
For what it's worth here is Claude Sonnet's asseessment of the logs' timing:
Looking at the debug logs, I can identify where prek is spending its time compared to
pre-commit. The main performance bottlenecks are:
Time Distribution Analysis
From the timestamps in the logs, here's where the time is going:
-
Health checking of installed hooks (~108ms)
- Lines show multiple Python version checks being executed sequentially
- 5 separate health checks running Python with
-I -c to verify versions
- This happens at
09:32:48.128 to 09:32:48.256
-
Serial hook execution (largest time sink)
- debug-statements: ~515ms (09:32:48.285 → 09:32:48.800)
- name-tests-test: ~444ms (09:32:48.817 → 09:32:49.261)
- toml-sort-fix: ~249ms (09:32:49.272 → 09:32:49.520)
- add-trailing-comma: ~597ms (09:32:49.524 → 09:32:50.122)
- pyupgrade: ~879ms (09:32:50.125 → 09:32:51.004)
- ruff check: ~361ms (09:32:51.008 → 09:32:51.369)
-
Multiple git diff calls
- Running
git diff before every hook (~10 times total)
- Each takes ~3-4ms, but adds up
Why It's Slower
The logs show concurrency=4 for several hooks, but you're still seeing significant serial
execution time. The likely issues are:
- Hook health checking overhead - pre-commit likely caches this better or skips it
- Git diff being called repeatedly - once before each hook instead of once upfront
- Process spawning overhead - each hook execution involves spawning Python processes
- Possible inefficient parallelization - despite
concurrency=4, hooks may not be batching
files optimally
Quick Wins
To speed this up, prek could:
- Cache health check results more aggressively
- Run
git diff once and reuse results
- Batch file processing more efficiently within hooks
- Consider running independent hooks in parallel (e.g.,
check-toml and check-yaml could run
simultaneously)
The total runtime is ~3.5 seconds, with most time spent in Python tool execution (pyupgrade,
add-trailing-comma, etc.) rather than in prek's core logic.
and its comparison to pre-commit:
Wow, that's a significant difference! Let me compare:
Comparison
| Hook |
pre-commit |
prek |
Difference |
| check-toml |
0.19s |
~instant |
- |
| check-yaml |
0.38s |
~instant |
- |
| debug-statements |
0.10s |
0.52s |
5.2x slower |
| end-of-file-fixer |
0.24s |
~instant |
- |
| name-tests-test |
0.11s |
0.44s |
4x slower |
| trailing-whitespace |
0.11s |
~instant |
- |
| toml-sort-fix |
0.25s |
0.25s |
same |
| add-trailing-comma |
0.42s |
0.60s |
1.4x slower |
| pyupgrade |
0.49s |
0.88s |
1.8x slower |
| ruff |
0.11s |
0.36s |
3.3x slower |
| ruff-format |
0.01s |
0.02s |
2x slower |
Key Findings
prek is significantly slower on hooks that process multiple files concurrently:
debug-statements: 5.2x slower
name-tests-test: 4x slower
ruff check: 3.3x slower
The pattern suggests that despite prek showing concurrency=4 in the logs, it's not
batching/parallelizing files as efficiently as pre-commit.
Looking at the prek logs more carefully:
TRACE Executing `cd ... && python3 .../debug-statement-hook tests/basic_permutations_test.py [...]`
TRACE Executing `cd ... && python3 .../debug-statement-hook tests/expressions_test.py [...]`
It appears to be spawning separate processes for small batches of files, while pre-commit
likely passes all 11 files to a single invocation of each hook, letting the hook itself handle
the files efficiently.
The overhead of spawning multiple Python processes (each with startup cost) is killing performance.
That's your bottleneck!
Summary
I’ve just taken prek for a spin and while the hook installation was faster (maybe 3-4x!), meaning overall run the first time (after wiping the cache dirs for level playing field) was faster, subsequent runs were slower (by about 0.5s - 1s) because somehow prek is slower to execute the hooks than pre-commit.
I presume this is worth a bug report given speed is prek’s primary goal, and hooks are likely going to be executed more often than they are installed (at least locally)
Platform
Linux 5.15.0-125-generic x86_64 GNU/Linux
Version
prek 0.2.5
.pre-commit-config.yaml
Click to show
Log file
Click to show
For what it's worth here is Claude Sonnet's asseessment of the logs' timing:
Looking at the debug logs, I can identify where
prekis spending its time compared topre-commit. The main performance bottlenecks are:Time Distribution Analysis
From the timestamps in the logs, here's where the time is going:
Health checking of installed hooks (~108ms)
-I -cto verify versions09:32:48.128to09:32:48.256Serial hook execution (largest time sink)
Multiple
git diffcallsgit diffbefore every hook (~10 times total)Why It's Slower
The logs show
concurrency=4for several hooks, but you're still seeing significant serialexecution time. The likely issues are:
concurrency=4, hooks may not be batchingfiles optimally
Quick Wins
To speed this up,
prekcould:git diffonce and reuse resultscheck-tomlandcheck-yamlcould runsimultaneously)
The total runtime is ~3.5 seconds, with most time spent in Python tool execution (pyupgrade,
add-trailing-comma, etc.) rather than in prek's core logic.
and its comparison to pre-commit:
Wow, that's a significant difference! Let me compare:
Comparison
Key Findings
prek is significantly slower on hooks that process multiple files concurrently:
debug-statements: 5.2x slowername-tests-test: 4x slowerruff check: 3.3x slowerThe pattern suggests that despite
prekshowingconcurrency=4in the logs, it's notbatching/parallelizing files as efficiently as
pre-commit.Looking at the prek logs more carefully:
It appears to be spawning separate processes for small batches of files, while
pre-commitlikely passes all 11 files to a single invocation of each hook, letting the hook itself handle
the files efficiently.
The overhead of spawning multiple Python processes (each with startup cost) is killing performance.
That's your bottleneck!