You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
GIF playback involves bitmapping individual frames, scaling them down to decrease memory usage (optional), and displaying them by swapping the bitmaps on screen. There needs to be a bit of a buffer to support this playback without stuttering. Bitmapping is CPU intensive, so there are advantages of caching bitmaps in memory to save CPU time. It's classic CPU vs memory trade-off.
Gifu has a dedicated animator with a buffer (FrameStore) that holds up to 50 frames in memory. If you visualize the playback, it looks something like this:
There are a couple of issues in which the system doesn't do the best possible job in terms of managing the system resources:
If a GIF has over 50 frames, Gifu keeps re-bitmapping the same frames, even if the free RAM is abundant.
Preparing the GIF for rendering by pre-loading the first 50 frames delays its playback.
If you display the same GIF in multiple views, the cached frames and the work to generate them are not shared between the animators.
There is no ceiling on how many GIFs can be played at the same time. If you end up playing too many, you may oversaturate both the CPU and the RAM, causing all of them to stutter, or may even get the app terminated.
When the app is suspended, the bitmapped frames stay in memory, increasing the chance the Watchdog terminates the app.
The framework doesn't respond to memory warnings.
Suggested Solution
Specifying the buffer size in terms of the number of frames is not optimal. There may be GIFs with few high-resolution frames, so they use too much memory. Or there may be GIFs with many tiny frames, but Gifu will not be able to hold all the frames in memory.
I suggest thinking about the upper limit in terms of the number of MB of RAM or the percentage of RAM. The framework could leverage NSCache to cache the frames. So, to summarise, I propose the following changes:
Identify the minimum buffer size required for smooth playback. It should be a maximum of two or three frames on modern CPUs.
Determine a fallback strategy if the production of frames is slower than consumption
Add a shared cache (NSCache) to store the bitmapped frames in memory
The cache should manage a single pool of memory, but individual images should have dedicated slots in it, so that when the animator is deallocated, it could also remove all of the associated data from the cache.
Add a shared system for producing the frames that could coalesce the requests for the same frames and manage how many images can be played in parallel
Clear cache for a given image when its playback stops
Clear cache when the app goes into the background
Also, clear the playback buffer and only leave the single (current) frame in memory
Provide an API for injecting a custom cache instance in case the app that uses the framework wants to leverage its own cache instance and control its size and cleanup policy
Automatically determine the number of GIFs that can be animated in parallel based on their size (this should be opt-in)
These suggestions are largely theoretical, but they are based on the following assumptions that I tested and that were also explained in the following WWDC session:
On iOS, it's nearly impossible to get the app terminated by allocating a ton of memory as long as the app responds to memory warnings and clears it. However, to be a good citizen, the app should not use too much memory, or it may get other apps killed.
If the app is suspended and it's using a lot of memory, it significantly increases the risk of it getting terminated.
The text was updated successfully, but these errors were encountered:
@kean Recently I started reviewing the entire codebase, including this aspect, but my involvement with other projects has significantly slowed that down. I am hoping to resume that, including going over this issue, in the coming weeks.
The current state
GIF playback involves bitmapping individual frames, scaling them down to decrease memory usage (optional), and displaying them by swapping the bitmaps on screen. There needs to be a bit of a buffer to support this playback without stuttering. Bitmapping is CPU intensive, so there are advantages of caching bitmaps in memory to save CPU time. It's classic CPU vs memory trade-off.
Gifu has a dedicated animator with a buffer (
FrameStore
) that holds up to 50 frames in memory. If you visualize the playback, it looks something like this:Issues
There are a couple of issues in which the system doesn't do the best possible job in terms of managing the system resources:
Suggested Solution
Specifying the buffer size in terms of the number of frames is not optimal. There may be GIFs with few high-resolution frames, so they use too much memory. Or there may be GIFs with many tiny frames, but Gifu will not be able to hold all the frames in memory.
I suggest thinking about the upper limit in terms of the number of MB of RAM or the percentage of RAM. The framework could leverage
NSCache
to cache the frames. So, to summarise, I propose the following changes:NSCache
) to store the bitmapped frames in memoryThese suggestions are largely theoretical, but they are based on the following assumptions that I tested and that were also explained in the following WWDC session:
The text was updated successfully, but these errors were encountered: