Skip to content

fix: correct VectorCache capacity and CacheHolder instance pooling - #3361

Merged
pauldendulk merged 10 commits into
mainfrom
fix_vector_cache
May 19, 2026
Merged

pauldendulk merged 10 commits into
mainfrom
fix_vector_cache

Conversation

@pauldendulk

Copy link
Copy Markdown
Member

What

Two bugs in the VectorCache / CacheHolder caching infrastructure that together made the vector cache completely non-functional.

Bug 1 — Math.Min in VectorCache capped capacity to 1

VectorCache.cs used Math.Min(capacity, 1) when constructing the LruCache. Since Math.Min(30000, 1) == 1, the cache could only ever hold a single entry regardless of the configured capacity. Any frame with more than one unique key caused constant eviction and recreation of Skia objects.

Fix: Changed to Math.Max(capacity, 1) so the configured capacity is honored and only a floor of 1 is enforced.

Bug 2 — CacheHolder.Get<T>() didn't pass this to CacheTracker

CacheHolder.Get<TResult>() returned new CacheTracker<TResult>((TResult)temp) — the single-argument constructor that leaves _holder == null. When the caller disposed the CacheTracker, Dispose() saw _holder == null and called DisposeIfDisposable(), destroying the Skia resource outright instead of returning it to the holder. Subsequent lookups for the same key found a CacheHolder with _instance == null, fell through to the uncached fallback, and created a fresh object every time.

Fix: Changed to new CacheTracker<TResult>(this, (TResult)temp) so the holder reference is preserved and Dispose() correctly returns the instance via SetInstance.

Impact

With both bugs present the cache was effectively a no-op: every render frame recreated all SKPath, SKPaint, SKTypeface, and label-bitmap objects from scratch. Layers with many features (lines, polygons, labels) would see O(N features) allocations per frame instead of O(distinct styles). Label layers were worst affected because CreateLabelAsBitmap renders a small bitmap per unique label text.

Relates to #3328

@pauldendulk pauldendulk added the PR type: 🐛 Fix A bug fix or patch for existing functionality. label May 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

PR type: 🐛 Fix A bug fix or patch for existing functionality.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant