We seem to have a memory leak caused by images in Ionic framework - causes heavy memory usage over time and then causes app to become unstable and eventually forces WKWebView to refresh (WKWebView flashes white) which resets the app.
This is obviously not ideal as it means the app is not stable and is likely to break in a production environment.
Also, leaving the app after a long period of activity, and coming back to it, can also trigger a forced WKWebView refresh.
Bug reproduction repo: https://github.com/4bsolut/cards
See video gif:
https://github.com/4bsolut/cards/raw/main/GIF-2021-10-20-14-07-27.gif?raw=true
The video was recorded while 'accepting and rejecting' a bunch of 'image cards'
And here's the memory chart with the bug reproduction demo in action - you can see there's a huge spike in memory before the app crashes and force refreshes / resets:
https://user-images.githubusercontent.com/2399351/138188417-c82eaf86-8a42-483a-b4dd-e973804d3309.gif
Steps to Reproduce
- Load images in an Ionic page eg. such as through cards containing images (as in the code reproduction URL).
- Hide or remove images as appropriate.
- Load some more images (without navigating away from the current page).
- Eventually WKWebView will run out of memory because garbage collection / memory cleanup doesn't seem to happen for the images.
- App will eventually become unstable and will either become non-responsive for user input or WkWebView will refresh.
Additional Information
Seems to be fine in iPhone emulator, but get the 'white flash' refresh / crash on actual device.
Tested using actual devices: iPhone 12 Pro (iOS 15.0.2) and iPhone XR (iOS 13.4.1).
Any help would be appreciated!
UPDATE:
tl;dr - Seems to be a lot of memory usage caused by layers...
Ionic have provided some very thorough debugging and support:
There are two issues here:
When adding new cards to the DOM, the memory spikes from ~30mb to ~300mb as a result of a large number of layers being created in WebKit. After these cards are added, the layers are not cleaned up so the memory usage stays at around ~300mb. Issue 1 is caused by both transition: all 0.3s ease-in-out; on line 44 of cards.component.scss and transition: opacity 0.3s ease-in-out; on line 74 of the same file. The problem here is that the all keyword means you are asking the browser to also transition the z-index that you are setting inline on the card element on line 22 of cards.component.html. This is going to force WebKit to create separate layers as it tries to animate, thus drastically increasing memory usage. It looks like you only want to transition the transform property, so I would change this to transform instead of all. For the image, I recommend removing the opacity transition here. Transitioning the opacity is forcing the image to get composited, but it will also cause any overlapping elements to get composited too, causing another memory spike.
Issue 2 is caused by the will-change on line 43 of cards.component.scss. will-change causes the browser to perform optimizations on elements before the elements actually change. However, will-change should only be used as a last resort and not as a way of pre-optimizing your app. Additionally, will-change should not be used on too many elements as it can cause a lot of resources to be consumed. I recommend removing this will-change to allow resources to get cleaned up. See https://developer.mozilla.org/en-US/docs/Web/CSS/will-change for more information on will-change.
To summarize:
Change transition: all 0.3s ease-in-out to transition: transform 0.3s ease-in-out in the .project--card selector. Remove transition: opacity 0.3s ease-in-out; in the .project--card img selector. Remove will-change: transform; in the .project--card selector. I cannot find anything in Ionic's code that would contribute to these issues. Can you try doing those 3 suggestions and let me know if they resolve the issue?