Repository navigation
perf(thumbnails): reuse a decode the live preview cache already holds - #7
Closed
thetalkingdrum wants to merge 1 commit into
Closed
thetalkingdrum wants to merge 1 commit into
thetalkingdrum wants to merge 1 commit into
Conversation
Update Thumbnails decodes through its own PreviewManager, so a frame the canvas or the neighbor prefetch had just decoded was read from the source again; on a slow network share that is a 15-20 s read per frame (marcinz606#1232). The gain is bounded: the live cache holds at most preview_cache_max_entries (8) decodes and the open frame is excluded, so at most ~7 of a 49-frame roll. - PreviewBufferCache.peek: a lookup that leaves the LRU order unchanged. - _linear_preview_key: every plain-frame put and lookup in PreviewManager builds its key here (pure refactor of six inline copies). - PreviewManager.peek_linear_preview: never decodes, never puts. - ThumbnailRenderWorker takes the live service and peeks it first for plain frames (not stitch, HDR or RGB triplet), copying the buffer and metadata arrays so the pipeline never writes into the navigation cache; a miss falls back to the private cache as before. Hits and misses log at debug. - Half-frame assets and roll forks key differently on the live path and always miss; decode params that differ between saved settings and the resolved roll config miss correctly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W1MEH5L17tDmpmz1H47dap
thetalkingdrum
marked this pull request as ready for review
September 30, 2026 20:28
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.
Part of marcinz606#1232.
ThumbnailRenderWorkerdecodes through its ownPreviewManager(thumbnail_render_preview_service) and never consults the livepreview_service, so a frame the canvas or the neighbor prefetch just decoded is read over the network again: 15–20 s per frame on the reporter's SMB share.The gain is bounded.
preview_cache_max_entries = 8and the open frame is already excluded from the refresh, so on the reporter's 49-frame roll this saves at most ~7 reads. The bulk of the time stays on I/O. This is a cheap win, not a fix for slow shares.Changes
PreviewBufferCache.peek(key): likeget, under the lock, but leaves the LRU order unchanged._linear_preview_key(...): one module-level helper inpreview_manager.py. All six identical inlinePreviewCacheKey(...)builds for a plain-frame decode now use it, including theputsite, so a stored decode and a later lookup can't drift apart. Pure refactor; every key field is unchanged.PreviewManager.peek_linear_preview(...): builds the key with the helper and returnsself._cache.peek(key). It never decodes and never puts.ThumbnailRenderWorker(preview_service, live_preview_service=None); the controller passesself.preview_service. For plain frames only (not stitch, HDR or RGB triplet, using the decode paths' own predicates), the worker peeks the live cache first and falls back to the private service on a miss. The live cache is read-only here: a roll-wide refresh never evicts or reorders the navigation cache.np.copy'd beforerun_pipeline. That's milliseconds against a network read, and it avoids having to prove the CPU stages never write in place.logger.debughit/miss line per frame, so real-world hit rates can be checked.Key parity (where hits can silently fail)
half_slice. The thumbnail path looks upbase_hash(...)with no slice and slices afterwards, so those entries are never found. Accepted for now; the keys are not unified in this PR.use_camera_wb,positive_source,highlight_mode,bake_camera_wb,demosaicandlens_*from the raw saved settings, while the refresh uses the resolved config with roll defaults applied. When they differ, a miss is correct, because the cached decode was made with other params.full_resolution=Falseentries can match, which is also correct.Tests
peekleaves the LRU order unchanged;getstill reorders; an absent key misses.peek_linear_previewhits a decode cached byload_linear_previewand misses on a different WB or hash, without calling the loader._neighbor_prefetch_task(...)is found by the refresh's lookup.test_uses_a_private_preview_cachestill passes, and the controller wires the live service in.make all: lint and type clean, 7326 passed. A later docstring-only change was checked with lint and format.Still to check (manual)
Open a roll, step through 5–6 frames, then press Update Thumbnails. The debug log should show hits for the visited and prefetched frames and misses for the rest.
🤖 Generated with Claude Code
https://claude.ai/code/session_01W1MEH5L17tDmpmz1H47dap
Generated by Claude Code