How Media Results Caching Improves Search Performance in Hydrus
Hydrus accelerates repeated searches by storing file metadata in an in-memory MediaResultCache that eliminates redundant SQLite queries through weak-reference dictionaries and a short-term FIFO buffer.
Hydrus is a comprehensive media tagging and management application maintained in the hydrusnetwork/hydrus repository. When users navigate through large collections or refine search filters, the media results caching layer prevents the database from re-executing expensive joins by reusing previously constructed metadata objects.
The MediaResultCache Architecture
The cache implementation resides in hydrus/client/media/ClientMediaResultCache.py and employs a dual-layer storage strategy to balance memory efficiency with retrieval speed.
Weak-Reference Dictionaries
The cache maintains two weak-reference mappings: _hash_ids_to_media_results and _hashes_to_media_results. These dictionaries hold MediaResult objects only while they remain referenced elsewhere in the application (such as by the UI). When the last external reference drops, the weak references automatically clear the entry, preventing unbounded memory growth.
FIFO Timeout Buffer
To handle rapid successive queries—such as when users refresh tags or toggle filters—the cache includes _fifo_timeout_cache. This FIFO queue forces recently fetched results to persist for approximately 2 minutes even if no other component currently references them (lines 43–48), ensuring that immediate follow-up searches hit the cache rather than triggering redundant database work.
Cache Hit and Miss Workflow
When the database layer in hydrus/client/db/ClientDBMediaResults.py needs to resolve metadata for a set of files, it first queries the cache through GetMediaResultsAndMissing (lines 57–80).
# Example search returning hash IDs
hash_ids = [12345, 67890, 11223]
# Cache lookup splits the request into cached and missing
cached_results, missing_hash_ids = media_result_cache.GetMediaResultsAndMissing(hash_ids)
if not missing_hash_ids:
# Cache hit: instant return with no SQLite work
media_results = cached_results
else:
# Cache miss: only missing IDs trigger database queries
media_results = db_media_results.GetMediaResults(hash_ids)
The GetMediaResults method (lines 91–99) implements this logic by delegating to the cache first. For any missing hash IDs, it constructs a temporary table, executes targeted joins against SQLite, builds ClientMediaResult objects (defined in hydrus/client/media/ClientMediaResult.py), and then populates the cache via AddMediaResults (lines 31–34 and 55–70).
Why This Speeds Up Searches
Media results caching delivers performance gains through four core mechanisms:
- Eliminates repeated full-table scans: Searches that revisit the same files never re-execute the large
SELECT … FROM files_info …joins for cached entries. - Reduces object construction overhead: Building
ClientMediaResultinstances—which bundle tags, timestamps, locations, ratings, and notes—is CPU-intensive; the cache returns existing objects. - Maintains UI responsiveness: Cache hits return immediately on the main thread, while misses are processed in background threads to prevent interface stalls.
- Provides graceful memory decay: Weak references allow the garbage collector to reclaim memory automatically when results are no longer needed.
Summary
- Hydrus implements media results caching through the
MediaResultCacheclass inhydrus/client/media/ClientMediaResultCache.py. - Weak-reference dictionaries (
_hash_ids_to_media_results,_hashes_to_media_results) store objects only while actively referenced elsewhere. - A 2-minute FIFO timeout cache retains recently accessed results to serve rapid successive queries without database hits.
- The database layer (
ClientDBMediaResults.py) always queries the cache first viaGetMediaResultsAndMissing, executing SQLite joins only for missing hash IDs. - New results are inserted back into the cache through
AddMediaResults, ensuring subsequent searches benefit from the cached data.
Frequently Asked Questions
How long do media results stay in the FIFO timeout cache?
Results remain in the _fifo_timeout_cache for approximately 2 minutes even when no other component references them. This duration prevents cache misses during rapid UI interactions like tag refreshes or filter toggles.
What happens when the cache reaches its memory limit?
The cache does not use a hard size limit. Instead, it relies on weak references in _hash_ids_to_media_results and _hashes_to_media_results. When the UI or other components release their references to a MediaResult, the garbage collector automatically removes the entry from the weak-reference dictionaries, allowing memory to be reclaimed naturally.
Can the media results cache cause stale data issues?
No. According to the hydrusnetwork/hydrus source code, the cache is designed to store immutable metadata snapshots. When file metadata changes (such as tag modifications), the system invalidates or updates the specific cached entries, ensuring subsequent searches retrieve current data while still benefiting from caching for unchanged files.
Which database operations are skipped on a cache hit?
When GetMediaResultsAndMissing returns a complete set of cached results (empty missing list), the database layer skips: (1) creating temporary tables for the hash ID list, (2) executing SELECT joins against files_info and related tables, and (3) constructing new ClientMediaResult Python objects. This reduces the operation from potentially hundreds of milliseconds to microseconds.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →