Repository navigation
FileCache: thread-safe lock, binary-search lookups, cache lock handed on quickly and expiring like MATLAB's - #89
Merged
Conversation
get_cache() returns one FileCache per process, and BinaryTable.has_lock was one flag on it, so while one thread held the lock every other thread took the "already held" path and rewrote the index unlocked. A per-table threading.Lock now serialises threads; the lock file still serialises processes. is_file, add_file and touch scanned the index row by row, reopening it for every row, although it is kept sorted; they now binary-search. find_row's unsorted path reads the column once. checkout_lock_file slept a whole second between checks; it now checks after 5 ms and backs off to 0.25 s within the same overall budget. Found through NDI's lightsheet viewer, where adding a downloaded tile to the cache took about a minute with tens of thousands of cached files and many download threads. The MATLAB side of the lookup and retry changes is VH-Lab/DID-matlab#221. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJ9PUeM7x2vLsg8FcZQfXo
Contributor
Author
|
Bridge coverage vs DID-matlab is red. All three problems it reports come from DID-matlab
None of these touches Once VH-Lab/DID-matlab#221 merges, this check will also flag Generated by Claude Code |
get_lock called checkout_lock_file with its defaults, a one-hour expiry, where MATLAB's binaryTable/getLock passes (30, 1, 20). A holder killed while updating the cache index -- an NDI viewer quitting while a daemon download thread was adding a tile -- left a lock every other process then waited 30 s on and gave up, for the next hour: each fetched tile took 30 s more and landed outside the cache. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJ9PUeM7x2vLsg8FcZQfXo
A waiter looks once a second, as before, unless its caller passes max_poll_interval; then it looks again after 5 ms and backs off to at most that interval. BinaryTable.get_lock passes 0.1 s: its holders keep the lock for milliseconds. Callers whose locks guard long operations (thousands of documents into a database) keep the old cadence. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJ9PUeM7x2vLsg8FcZQfXo
…lab#221 DID-matlab#221 merged (057f641, a merge commit, so these stay reachable). The commits touching each file since its recorded hash are exactly that PR's -- 3041f77, 915f92b, bd369da -- whose changes this branch already carries. Point each entry at its file's last-touching commit and drop the "pending" wording. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EJ9PUeM7x2vLsg8FcZQfXo
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.
Why
In NDI's lightsheet viewer, adding a downloaded tile to the file cache took 30–60 s, while the download itself took 3–7 s. The time went into this cache.
Changes (
src/did/file.py)get_cache()returns oneFileCacheper process, andBinaryTable.has_lockwas a single flag on it. While one thread held the lock, every other thread sawhas_lockTrue, took the "already held" path, and rewrote the index without the lock. A per-tablethreading.Locknow serializes threads fromget_lockto the outermostrelease_lock; the lock file still serializes processes.has_lockcounts as held only for the thread that took it.reset_lock_stateonly clears the calling thread's own hold.is_file,add_fileandtouchscanned the index row by row, reopening it for every row (about 0.2 s per lookup at 20,000 files). The index is kept sorted by name, so these now usefind_row(..., sorted=True).find_row's unsorted path, still used byremove_fileandcheck, reads the column once.checkout_lock_filetakes an optionalmax_poll_interval. When it's given, a waiter checks again after 5 ms and backs off to at most that interval. When it's omitted, a waiter still checks once a second, as before, so long-held locks keep their cadence.BinaryTable.get_lockpasses 0.1 s.get_lockusedcheckout_lock_file's defaults, a one-hour expiry. A holder killed mid-update (an NDI viewer quitting while a daemon download thread was adding a tile) left a lock that every other process then waited 30 s on and gave up, for the next hour. This was the 30-s-per-tile stall seen in the viewer.Changes 2 and 3 are also made in VH-Lab/DID-matlab#221; MATLAB already uses the 20 s expiry. Until DID-matlab#221 merges, Python is ahead, and the bridge entries'
decision_logs say so. After it merges, the drift check will flagbinaryTable,fileCacheandcheckout_lock_file, and theirmatlab_last_sync_hashshould be bumped to the merge commit.Testing
tests/test_file_cache.py:currentSizeis right.is_filehits and misses are correct, and an unsortedfind_rowopens the index once.ruffandblackare clean.bin/check_bridge_coverage.pyagainst DID-matlabmainreports 3 problems, all present onmainbefore this change:+fun/timestamp.mhas no entry, anddocumentandsqlitedbhave drifted. This PR adds none.🤖 Generated with Claude Code
https://claude.ai/code/session_01EJ9PUeM7x2vLsg8FcZQfXo