Skip to content

perf: cache parsed flags and let the raster cache retain them - #1

Draft
ik-make wants to merge 2 commits into
messengerxfrom
fix/skwasm-flag-image-cache
Draft

perf: cache parsed flags and let the raster cache retain them#1
ik-make wants to merge 2 commits into
messengerxfrom
fix/skwasm-flag-image-cache

Conversation

@ik-make

@ik-make ik-make commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

Context

Found while chasing a Skwasm renderer crash in a 145-row language picker on Flutter 3.47.2 (--wasm, single-threaded skwasm). The crash itself turned out to be a jovial_svg bug, not a country_flags bug — it is fixed separately in zathras/jovial_svg#142. These two changes are pure performance work, verified not to be required for the crash fix.

1. Share a ScalableImageCache

_FlagImage calls ScalableImageWidget.fromSISource without a cache:. Per jovial_svg's docs on that constructor:

NOTE: If no cache is provided, a default of size zero is used.

So every flag that scrolls out of view is evicted immediately and re-parsed when it scrolls back. Some assets in this pack are large (rs.si ~500KB, pe.si ~127KB, es.si ~77KB), so a scroll repeatedly re-parses hundreds of KB on the main thread.

A single static cache, sized to hold the whole pack, removes that.

2. isComplex: true

CustomPaint.isComplex defaults to false, so the raster cache never retains a painted flag and the whole compact image is replayed every frame. Flags are detailed vector art (several carry a coat of arms), which is exactly the case isComplex exists for.

Notes

No API change, no asset change. Both are opt-out-free improvements for any consumer rendering many flags at once.

ik-make and others added 2 commits August 29, 2026 01:43
ScalableImageWidget.fromSISource falls back to a zero-size cache when none is
supplied, so every flag scrolling out of view is evicted immediately and
re-parsed on the way back. In a long scrolling list this also releases the
native Path objects that already-queued pictures still reference, and Flutter
web (Skwasm) then traps with "memory access out of bounds".

Share one ScalableImageCache across all _FlagImage instances, sized to hold the
whole flag pack.

Co-authored-by: Cursor <cursoragent@cursor.com>
CustomPaint.isComplex defaults to false, so the raster cache never retains a
flag and the whole compact image is replayed on every frame. Several flags
carry a coat of arms (rs.si is ~500KB, pe.si ~127KB), which makes that replay
expensive during a scroll and churns a large number of short-lived native
Path objects.

Co-authored-by: Cursor <cursoragent@cursor.com>
@ik-make ik-make changed the title fix: cache parsed flag images to stop Skwasm renderer crash perf: cache parsed flags and let the raster cache retain them Aug 28, 2026
@zathras

zathras commented Aug 29, 2026

Copy link
Copy Markdown

IMHO it's unlikely to be a jovial_svg bug. Rather, it appears to be a bug in the Skwasm renderer that you were able to work around (partially?) in jovial_svg. See zathras/jovial_svg#143 .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants