# How Media Results Caching Improves Search Performance in Hydrus

> Discover how Hydrus caching dramatically speeds up searches. Learn how media results caching uses in-memory storage to eliminate redundant queries and boost performance.

- Repository: [Hydrus Network Developer/hydrus](https://github.com/hydrusnetwork/hydrus)
- Tags: performance
- Published: 2026-03-03

---

**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`](https://github.com/hydrusnetwork/hydrus/blob/main/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`](https://github.com/hydrusnetwork/hydrus/blob/main/hydrus/client/db/ClientDBMediaResults.py) needs to resolve metadata for a set of files, it first queries the cache through `GetMediaResultsAndMissing` (lines 57–80).

```python

# 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`](https://github.com/hydrusnetwork/hydrus/blob/main/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 `ClientMediaResult` instances—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 `MediaResultCache` class in [`hydrus/client/media/ClientMediaResultCache.py`](https://github.com/hydrusnetwork/hydrus/blob/main/hydrus/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`](https://github.com/hydrusnetwork/hydrus/blob/main/ClientDBMediaResults.py)) always queries the cache first via `GetMediaResultsAndMissing`, 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.