⚡️ Speed up method TestsCache.compute_file_hash by 53% in PR #753 (test_cache_revival)#810
Merged
KRRT7 merged 2 commits intoOct 10, 2025
Conversation
The optimized code achieves a 52% speedup by replacing the traditional file reading approach with a more efficient buffered I/O pattern using `readinto()` and `memoryview`.
**Key optimizations:**
1. **Pre-allocated buffer with `readinto()`**: Instead of `f.read(8192)` which allocates a new bytes object on each iteration, the code uses a single `bytearray(8192)` buffer and reads data directly into it with `f.readinto(mv)`. This eliminates repeated memory allocations.
2. **Memory view for zero-copy slicing**: The `memoryview(buf)` allows efficient slicing (`mv[:n]`) without copying data, reducing memory overhead when updating the hash with partial buffers.
3. **Direct `open()` with unbuffered I/O**: Using `open(path, "rb", buffering=0)` instead of `Path(path).open("rb")` avoids the Path object overhead and disables Python's internal buffering to prevent double-buffering since we're managing our own buffer.
**Performance impact**: The line profiler shows the critical file opening operation dropped from 83.4% to 62.2% of total time, while the new buffer operations (`readinto`, `memoryview`) are very efficient. This optimization is particularly effective for medium to large files where the reduced memory allocation overhead compounds across multiple read operations.
**Best use cases**: This optimization excels when computing hashes for files larger than the 8KB buffer size, where the memory allocation savings become significant, and when called frequently in batch operations.
Merged
Contributor
|
looks pretty cool! |
cmaloney
reviewed
Oct 10, 2025
| def compute_file_hash(path: str | Path) -> str: | ||
| h = hashlib.sha256(usedforsecurity=False) | ||
| with Path(path).open("rb") as f: | ||
| with open(path, "rb", buffering=0) as f: |
There was a problem hiding this comment.
path.open("rb", buffering=0) should also work / do the same thing here to resolve the lint issue.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
⚡️ This pull request contains optimizations for PR #753
If you approve this dependent PR, these changes will be merged into the original PR branch
test_cache_revival.📄 53% (0.53x) speedup for
TestsCache.compute_file_hashincodeflash/discovery/discover_unit_tests.py⏱️ Runtime :
301 microseconds→197 microseconds(best of36runs)⚡️ This change will improve the performance of the following benchmarks:
🔻 This change will degrade the performance of the following benchmarks:
{benchmark_info_degraded}
📝 Explanation and details
The optimized code achieves a 52% speedup by replacing the traditional file reading approach with a more efficient buffered I/O pattern using
readinto()andmemoryview.Key optimizations:
Pre-allocated buffer with
readinto(): Instead off.read(8192)which allocates a new bytes object on each iteration, the code uses a singlebytearray(8192)buffer and reads data directly into it withf.readinto(mv). This eliminates repeated memory allocations.Memory view for zero-copy slicing: The
memoryview(buf)allows efficient slicing (mv[:n]) without copying data, reducing memory overhead when updating the hash with partial buffers.Direct
open()with unbuffered I/O: Usingopen(path, "rb", buffering=0)instead ofPath(path).open("rb")avoids the Path object overhead and disables Python's internal buffering to prevent double-buffering since we're managing our own buffer.Performance impact: The line profiler shows the critical file opening operation dropped from 83.4% to 62.2% of total time, while the new buffer operations (
readinto,memoryview) are very efficient. This optimization is particularly effective for medium to large files where the reduced memory allocation overhead compounds across multiple read operations.Best use cases: This optimization excels when computing hashes for files larger than the 8KB buffer size, where the memory allocation savings become significant, and when called frequently in batch operations.
✅ Correctness verification report:
⏪ Replay Tests and Runtime
benchmarks/codeflash_replay_tests_4pj5qijs/test_tests_benchmarks_test_benchmark_discover_unit_tests__replay_test_0.py::test_codeflash_discovery_discover_unit_tests_TestsCache_compute_file_hash_test_benchmark_code_to_optimize_test_discoveryTo edit these changes
git checkout codeflash/optimize-pr753-2025-10-10T18.29.30and push.