Avalonia icon indicating copy to clipboard operation
Avalonia copied to clipboard

Fix excessive GlyphTypeface allocations in SystemFontCollection when FamilyName differs from requested

Open adirh3 opened this issue 1 month ago • 4 comments

What does the pull request do?

Fixes a cache miss issue in SystemFontCollection that causes repeated GlyphTypeface allocations when the platform returns a typeface with a different FamilyName than requested.

What is the current behavior?

When requesting a font, the platform may return a typeface with a different FamilyName than requested. For example:

  • Request "Segoe UI Variable Text" → returns typeface with FamilyName = "Segoe UI Variable"
  • Request "Microsoft YaHei" → returns typeface with FamilyName = "Microsoft YaHei UI"

The cache stores the typeface under the actual FamilyName, but subsequent lookups use the requested name. This causes cache misses on every request, creating new GlyphTypeface instances (with underlying HarfBuzzSharp.Face native resources) repeatedly.

This causes significant memory pressure during virtualized list/panel scrolling where the same font is requested many times per second.

What is the updated/expected behavior with this PR?

Typefaces are now cached under the requested family name key, ensuring subsequent lookups hit the cache. Repeated requests return the cached instance instead of allocating new ones.

How was the solution implemented (if it's not obvious)?

The fix ensures TryAddGlyphTypeface(familyName, key, glyphTypeface) is called with the requested familyName in both code paths:

  1. After base.TryGetGlyphTypeface succeeds
  2. After _platformImpl.TryCreateGlyphTypeface succeeds

Checklist

  • [x] Added unit tests (if possible)?
  • [ ] Added XML documentation to any related classes?
  • [ ] Consider submitting a PR to https://github.com/AvaloniaUI/avalonia-docs with user documentation

Breaking changes

None

Obsoletions / Deprecations

None

adirh3 avatar Dec 09 '25 19:12 adirh3

Have you tried https://github.com/AvaloniaUI/Avalonia/pull/19852 ?

Gillibald avatar Dec 09 '25 20:12 Gillibald

Have you tried #19852 ?

I haven't tried, just briefly looked at the SystemFontCollection changes it doesn't seem to cache on both requested and actual font family? I will have a deeper look tomorrow, but I guess you plan to merge this for 12.x release, and this problem seems to happen on 11.3 as well. For example, scrolling in Fluent Search with Segoe UI Variable Text font causing RAM spike to 1gb+ very easily, with thousands of glyphs created.

adirh3 avatar Dec 09 '25 20:12 adirh3

This targets 11.3 https://github.com/AvaloniaUI/Avalonia/pull/20207

Gillibald avatar Dec 09 '25 20:12 Gillibald

This targets 11.3 #20207

This one seems to fix the issue.

I might be missing something since #19852 is a big PR, but from what I can see it still has the bug: it caches the font under what the system returns ("Segoe UI Variable") rather than what was requested ("Segoe UI Variable Text"), so the next lookup misses the cache and creates a new allocation.

I haven't tested #19852 directly, so if you can confirm it actually fixes this we can close this. Otherwise, we could keep this open if you'd like a fix in master until #19852 is merged.

adirh3 avatar Dec 09 '25 23:12 adirh3