swiftui list drops to 41 fps with 2,000 rows and asyncimage on an iphone 12 performance
Feed screen, List of about 2,000 rows. Each row has a 60x60 remote thumbnail via AsyncImage, a title, a subtitle and a timestamp.
On recent hardware it is fine. On an iPhone 12 it hitches noticeably on fast scrolls and Instruments shows frame rate dipping to around 41 during flings, with the drops clustered where new rows come in.
Things I have already tried without much change: removing the timestamp formatting from the row body, giving rows a fixed height, and switching from LazyVStack in a ScrollView to List (this helped a bit).
The images are the obvious suspect but they are only 60x60 on screen so I assumed they were cheap.
@rueben_alsop · 2mo ago · 2 replies
Once images are handled, the next tier of things that cost frames in a List row:
AnyViewanywhere in the row. It erases the type, so the diffing machinery cannot tell that the structure is unchanged and re-evaluates more than it needs to.DateFormattercreated per row per redraw is genuinely expensive - hoist it to a static..frame,.paddingand.backgroundcombinations that each add a layout pass.Measure with the SwiftUI template in Instruments rather than guessing. The "View Body" track shows you which view's body is slow and how often it runs, and "Long View Body Updates" points at the specific offender. It is a much better use of an hour than shotgunning modifiers.
Reply
Report
@probe_to_ground · 2mo ago
The formatter one is embarrassingly common and has an easy fix now - the
.formatted()style APIs are cheaper than constructing a formatter, and if you need a custom one, astatic letcosts nothing after the first use.Reply
Report