RESOLVED FIXED295618
REGRESSION (273213@main): ImageBitmap fails to report memory cost
https://bugs.webkit.org/show_bug.cgi?id=295618
Summary REGRESSION (273213@main): ImageBitmap fails to report memory cost
Kevin
Reported 2025-07-08 21:39:29 PDT
Hi there, 👋 Since late March/early April 2025 (iOS 18.4 released March 31), we have been struggling significantly with involuntary reloads/crashes of the WKWebView/web browser for our app on iOS. While this increase in reloads began during that timeframe, we are no strangers dealing with Jetsam/memory issues on iOS. We have battled these limitations off and on in a notable way since 2019. It’s now become rather significant once again. We’ve spent the past 3 months working on trying to narrow down what might’ve changed. We’ve been: - Working with our customers. - Considering the changes across the various versions of our app. - Analyzing involuntary reload stats and other usage data in Sentry (error/reload tracking) and Pendo (user analytics). - Performing a large amount of testing to gather data and inform our theories. Our hypothesis is that a change introduced in iOS/WebKit 18.4 is what has tanked stability. Background Our app uses esri’s ArcGIS Maps SDK for JavaScript (https://developers.arcgis.com/javascript/latest/ ). It is a map control library similar to Mapbox. It uses WebGL, WebAssembly, Web Workers, etc.--more advanced Web APIs which may tax memory/resources. The problem primarily seems to be with customers who display esri “Web Maps” (https://developers.arcgis.com/javascript/latest/tutorials/display-a-web-map/ ) on the map. In particular, we’ve noticed that Web Maps containing a “Map Image Layer” (https://developers.arcgis.com/javascript/latest/sample-code/layers-dynamicdatalayer-raster/ ) seem particularly volatile. We’ve been able to remove our hybrid native/WKWebView/Capacitor app from the equation and can still reproduce the issue. We began by using esri’s own Map Viewer app (https://www.arcgis.com/apps/mapviewer/index.html ) which also uses the ArcGIS Maps SDK for JavaScript under-the-hood. We used the versions of Map Viewer in our customers’ respective on-prem esri “Portal” installations–the on-prem version of arcgis.com. We used the customer-specific maps they were having problems with in our app. We found that even just panning around those maps in Map Viewer would cause a reload within a few minutes. Creating a Reproduction Narrowing it down even further, and making an attempt to provide a simpler reproduction, we found the CodePen of an official esri sample for a Map Image Layer (https://developers.arcgis.com/javascript/latest/sample-code/layers-dynamicdatalayer-raster/ ). We forked this official CodePen and made only additive changes of workflow automation code (https://codepen.io/kevinkelchen/pen/vEOoqrq?editors=1000 ). The workflow automation maintains and displays an “Uptime” timer of how long the workflow has been running. The timer will stop when a reload occurs, and the uptime will persist across browser reloads to display how long the workflow ran before it reloaded. The automation simply pans the map slightly, and then pans it back to the starting position. It keeps doing this indefinitely until a reload occurs. Steps to Reproduce 1. On the iOS device, make sure the device’s display will not turn off automatically when not physically interacting with the device (Settings > Display & Brightness > Auto-Lock = Never). - A similar line of thinking also applies to idle timeouts that tools like BrowserStack, SauceLabs, AWS Device Farm, etc. might have. (We used BrowserStack for a subset of our testing.) 2. Close all the open apps, and restart the iOS device. - This is not really a requirement, but it might help for apples-to-apples testing regarding memory usage. 3. Open Safari. 4. Navigate to https://codepen.io/kevinkelchen/full/vEOoqrq 5. After the map has finished loading, tap the “Start Workflow” button. 6. The “Start Workflow” button should become disabled, the uptime timer should start incrementing, and the map should begin panning back and forth. 7. Allow this to run until a reload occurs. 8. After reload, the “Start Workflow” button should be enabled again, and the uptime timer should have a non-zero value that is no longer incrementing. This should be the amount of time the workflow ran before reloading. Reproduction Uptime From our testing following the above steps using an iPad 9th Gen on iOS 18.4, the uptime is generally 4-7 minutes (video: https://www.youtube.com/watch?v=xSW3lDjlBcY ). Comparatively, an iPad 9th Gen on iOS 18.1 can run for at least 60 minutes without a reload (video, which isn’t really interesting because a reload did not occur: https://www.youtube.com/watch?v=iw2hu9G0O4k ). We didn’t test much beyond 60 minutes, so not sure when it would have eventually popped, if at all. Also, we would’ve used iOS 18.3.x, but we didn’t have access to the same device model with that OS version, so iOS 18.1 is the closest we could get that was less than 18.4. In addition to the uptime depending on if it’s iOS 18.4+ or not, the device hardware itself may make a difference. If the device has more RAM, it may last longer before reloading. Memory Growth Being suspicious about memory consumption, we did some profiling. We’ve had a bit of a Catch-22 using the Safari dev tools for memory profiling since they tend to eventually crash when the device is low on memory. Instead, we used the macOS Activity Monitor to get a couple of alternative perspectives. Using Xcode simulators, we compared the simulator for an iPad 9th Gen on iOS 18.3.1 to the same device on iOS 18.4. In Activity Monitor on the Memory tab, we watched the memory for the process named “SimRenderServer (iPad (9th generation))”. Using the reproduction CodePen, here’s how they compared: iOS 18.3.1: - Memory before starting workflow: 204.4 MB - Memory usage decreases at all during workflow?: Yes - Memory when stopping workflow at 6 minutes: 309 MB - Memory after waiting 5 minutes while workflow is stopped: 195.5 MB iOS 18.4: - Memory before starting workflow: 209.3 MB - Memory usage decreases at all during workflow?: No - Memory when stopping workflow at 6 minutes: 1.56 GB - Memory after waiting 5 minutes while workflow is stopped: 1.56 GB It appears that iOS 18.4 changed behavior where the app no longer reclaims memory. Not sure if this illustrates what’s contributing to the reload (I suspect it is), or if it’s a red herring. Given the amount of RAM on these devices, I would very much expect reloads to occur in light of these memory characteristics. Similarly, in an attempt to see if the memory growth behavior is specific to iOS or perhaps part of WebKit–and also to take a look at 18.3.2 to narrow down when the behavior changed–we did a similar comparison of macOS Safari comparing macOS 15.3.2/Safari 18.3.2 to macOS 15.4/Safari 18.4. In Activity Monitor on the Memory tab, we watched the memory for the processes named “https://codepen.io” and “Safari”. Using the reproduction CodePen, here’s how they compared: macOS 15.3.2/Safari 18.3.2: - Memory before starting workflow: - codepen.io: 613 MB - Safari: 60 MB - Memory usage decreases at all during workflow?: - It would regularly build memory up to around 830 MB or so, then reclaim back down to about 770 MB. - Memory when stopping workflow at 6 minutes: - codepen.io: 810 MB - Safari: 60 MB - Memory after waiting 5 minutes while workflow is stopped: - codepen.io: 642 MB - Safari: 60 MB macOS 15.4/Safari 18.4: - Memory before starting workflow: - codepen.io: 510 MB - Safari: 54 MB - Memory usage decreases at all during workflow?: - Early on, it reclaimed memory a few times, but that seemed to stop after 10-15s. - Memory when stopping workflow at 6 minutes: - codepen.io: 1.07 GB - Safari: 54 MB - Memory after waiting 5 minutes while workflow is stopped: - codepen.io: 1.07 GB - Safari: 54 MB The memory not being reclaimed on macOS Safari was similar to iOS Safari. This perhaps points to a behavior change in WebKit. (Perhaps it’s also possible that the iOS/Jetsam threshold for WebKit was lowered, but there’s no evidence we’ve seen of that.) Searching the Web We tried to see if others were experiencing the same issue. We came across a Reddit thread which, given its tone, I will not link to here. However, there’s a Unity discussion thread (https://discussions.unity.com/t/webgl-is-not-working-on-safari-after-ios-18-4-update/1628007/25 ) and a related WebKit issue (https://bugs.webkit.org/show_bug.cgi?id=291677 ) that I’m linking to. What’s interesting about these is they pertain to iOS reloads when using WebAssembly and WebGL which the esri map also uses. Perhaps the esri Map Image Layer or certain esri Web Map features use some of the affected Web APIs more heavily. Or perhaps our issue is unrelated but was introduced in the same iOS version. The WebKit issue is marked as a duplicate and resolved, but some people are saying the issue wasn't fixed in iOS 18.5, such as here: https://discussions.unity.com/t/webgl-is-not-working-on-safari-after-ios-18-4-update/1628007/31 We had also tested an iOS 26.0 beta simulator and observed similar memory growth, but we did not test 26.0 on a real device to see if it reloaded. The memory growth doesn’t make us hopeful though that 26.0 will have a fix. General Reload Comments As mentioned earlier, we’ve been struggling with involuntary reloads since 2019. Our hope was that with newer devices with more RAM it would become a thing of the past. That has probably helped some, but it’s still present. It sounds like according to https://bugs.webkit.org/show_bug.cgi?id=268816#c2 there’s a way to provide feedback to Apple on the memory limits imposed by iOS on WebKit. I have yet to do so, but I plan to. I’m not privy to all the rationale for why the memory limit is so low for web apps. I’ve heard it’s a way to prevent web browser tabs from using unreasonable amounts of memory on devices that don’t traditionally have a lot of RAM. That intent is totally reasonable, but I think its execution deserves more nuance. I think the existing low limits make sense for browser tabs that are not in view, or while the web browser is minimized (apps themselves get killed in the background when minimized which is an expected user experience on mobile). But to kill the app while the user has it visible and is actively using it seems at the very least a bridge too far. What makes it worse is when you have an app like ours which is a hybrid native/WKWebView/Capacitor app, the web content virtually *is* the app. To kill it while the user is interacting with it seems to be way overboard. It’s not some rogue browser tab; it’s mission-critical enterprise software the user is interacting with trying to do their job. Meanwhile, there are probably many other iOS apps with traditional native UI components such as video games that can use way more memory/resources and yet they don’t crash while the user is actively using them. It would be a huge step forward even if hybrid native apps had some type of iOS Entitlement that App Store Review could issue to allow the main WKWebView to not be reloaded while visible. If relief graciously extends to web browser tabs, it also helps make the case that web apps on iOS are a viable alternative to the App Store–a subject of conversation the past few years. At any rate, those are just some musings I wanted to share. Closing Remarks I know this is probably more information than the typical issue, but I erred on the side of detail to provide what’s needed to help arrive at a fix sooner. If you have any questions, or if I can be helpful in providing anything further, please let me know! WebKit maintainers likely have many competing priorities, issues, and work, so thank you very much for taking the time to read and investigate this issue. It’s a major issue for us, and therefore it is so greatly appreciated! Thank you, and take care, Kevin
Attachments
Kevin
Comment 1 2025-07-10 13:30:00 PDT
It was buried in the details, but if the device has more RAM, it may last longer before reloading. Another important bit of information that I failed to mention is that a smaller viewport/screen size can also make the workflow last longer before reloading--probably because there's less map to draw. The videos and numbers for uptime provided in the OP were for an Apple iPad (9th generation, 10.2-inch, 2021) (https://www.gsmarena.com/apple_ipad_10_2_(2021)-11106.php ). It has 3 GB of RAM and has a larger viewport (tablet). We've also run the reproduction on a couple of other devices. Apple iPhone SE (2nd generation, 2020) (https://www.gsmarena.com/apple_iphone_se_(2020)-10170.php ) on iOS 18.5 lasts 19-21 minutes before reloading. It has 3 GB of RAM, but it has a smaller screen with less map to draw. Apple iPad Pro (12.9, 3rd generation, 2018) (https://www.gsmarena.com/apple_ipad_pro_12_9_(2018)-9387.php ) on iOS 18.5 lasts 5-6 minutes before reloading. It has 4 GB of RAM (1 GB more than the iPhone SE 2nd Gen), but it has a larger screen with more map to draw. Hope this helps. Thanks much, and take care, Kevin
Radar WebKit Bug Importer
Comment 2 2025-07-10 15:29:03 PDT
Kevin
Comment 3 2025-07-16 11:41:04 PDT
I wanted to give a big "THANK YOU!" to Alexey Proskuryakov for triaging this issue and noting it as a regression! ❤️ (I held off on doing so immediately because I didn't want to spam with an additional message, but I probably should have made our appreciation known sooner!) We did also open up a support case with esri linking to this WebKit issue. Since it appears like this is an acknowledged issue in WebKit/iOS, my guess is that esri will probably more or less wait for it to be fixed in WebKit/iOS. Regardless, please let me know if there's anything I can do (testing a build with customer data, looping in esri, etc.) to help move things along. Our Apple users will greatly appreciate the help! I am rooting for you! Thanks so much, and take care, Kevin
Kevin
Comment 4 2025-07-29 15:39:29 PDT
Hello there! 👋 I thought I would provide some additional context on user impact. Our application on iOS has about 7600 monthly active users. These 7600 users are mostly U.S. local government employees that work in the field maintaining our roads, bridges, signs, water systems, and other critical infrastructure assets. Their work is essential to the quality of life and safety of our communities and families. While reloads on iOS have happened for years due to iOS memory limitations, it has gotten bad enough with iOS 18.4 that an unprecedented number of customers have contacted our support team. We're at about 4 months of being impacted. Are there any thoughts on where this issue stands or when we can expect a fix? I know folks are probably super busy. At the same time, any insight would be greatly appreciated! Thanks so much, and take care, Kevin
Kevin
Comment 5 2025-09-09 07:57:32 PDT
Hello there! 👋 Is there anything anyone needs from us to help move this issue along? Thanks so much, and take care, Kevin
Kevin
Comment 6 2025-09-23 15:04:04 PDT
Thank you so much to Said Abou-Hallawa for reviewing this issue and CCing others! ❤️
Kimmo Kinnunen
Comment 7 2025-09-30 05:16:47 PDT
Kimmo Kinnunen
Comment 8 2025-09-30 05:20:20 PDT
Thank you for the report and spending time on the good repro case. Until the fix ships, you could workaround the issue by using ImageBitmap.close() to explicitly discard ImageBitmap contents at the moment the app does not need the contents anymore. This will improve the application memory use even after the fix ships. The application seems to hold on to number of ImageBitmaps in steady state operation. With my screen size, it appeared to be for example ~40 ImageBitmap instances. In case these are unintentional, you may investigate avoiding keeping these. In case these are intentional, then please disregard this observation.
Kevin
Comment 9 2025-09-30 08:58:54 PDT
THANK YOU SO MUCH, KIMMO!!! You are my hero! ❤️❤️❤️ 🎉🎉🎉 🚀🚀🚀 I am so, so thankful for you diving into this issue and PRing a fix!!! Since the ImageBitmap-related usage is in the esri SDK, I will share with the esri SDK team those ImageBitmap suggestions. I have a couple of questions if it's not too much to ask: 1. One thing I was curious about was if we determined what happened to cause the regression. Our theory is that something changed in 18.4 but we didn't know what. Do you have an idea of what that might have caused the regression? 2. What is the best way for our team to test the fix soon after it's merged? We could use Safari Tech Preview on macOS to check the memory growth as noted in the OP. Do you know roughly when Safari Tech Preview would release with the fix? While testing macOS would be good, iOS is really what matters to us. If we wanted to test iOS, I imagine that would involve putting an iOS device on the iOS beta program? Do you know roughly when an iOS beta would release with the fix? I greatly appreciate everything, Kimmo! Thank you very much, and take care! Kevin
Kimmo Kinnunen
Comment 10 2025-10-01 01:04:01 PDT
The regression is linked in the title, 273213@main, bug 267455 (unfortunate mistake, unfortunately no test coverage for the memory part) STP or iOS beta would be the first testable releases. We do not share the schedule for a fix to ship in these, though.
Kevin
Comment 11 2025-10-01 09:49:36 PDT
Hi Kimmo! 👋 Ah, ok! When I had seen the issue title change, I assumed in my excitement that it was the commit containing the fix. What you're saying definitely makes more sense. 😅 Given the January 2024 date on that regression commit, I would think the regression would've landed in Safari prior to 18.4 (which released March 2025). Perhaps that regression commit was a root factor that didn't play well with some other change that landed in 18.4? 🤔 At any rate, I appreciate the explanation! Thank you! Thank you likewise for the information on how we can test the fix! We will plan to test both STP and iOS beta. It's understandable that a schedule for shipping the fix is not shared. Will there be a way in the future to check if it has shipped and in what version? Like will this WebKit issue, the GitHub PR/tags, Safari release notes (https://developer.apple.com/documentation/safari-release-notes ), or some other place indicate the fix has shipped? Thanks so much again, Kimmo! It is always greatly appreciated! Take care, Kevin
EWS
Comment 12 2025-10-02 04:02:38 PDT
Committed 300870@main (6d1a61fa69df): <https://commits.webkit.org/300870@main> Reviewed commits have been landed. Closing PR #51560 and removing active labels.
Kevin
Comment 13 2025-10-02 06:46:05 PDT
So happy to see the fix get merged!!! Thanks so much again, Kimmo! Kevin
Kevin
Comment 14 2025-10-02 06:53:40 PDT
Oh, I just thought of a third question if it's not too much to ask. 🙂 I'll copy the other two from my prior message for convenience. 1. Given the January 2024 date on that regression commit, I would think the regression would've landed in Safari prior to 18.4 (which released March 2025). Perhaps that regression commit was a root factor that didn't play well with some other change that landed in 18.4? 🤔 2. Will there be a way in the future to check if it has shipped and in what version? Like will this WebKit issue, the GitHub PR/tags, Safari release notes (https://developer.apple.com/documentation/safari-release-notes ), or some other place indicate the fix has shipped? 3. Related to the previous question, do you know what major version of iOS this would land in? Would it just be iOS 26? I really appreciate your amazing help. Thank you very much, and take care! Kevin
Kevin
Comment 15 2025-11-03 07:08:08 PST
Hello there! 👋 I saw that Safari Technology Preview 130 released with the fix (https://developer.apple.com/documentation/safari-technology-preview-release-notes/stp-release-230 ), so I went ahead and tried it out on macOS. Compare this to the metrics in the OP. macOS 26.0.1/Safari Technology Preview 130: - Memory before starting workflow: - codepen.io: 726 MB - Safari: 91 MB - Memory usage decreases at all during workflow?: - It would regularly build memory up to around 780 MB or so, then reclaim back down to about 730 MB. - Memory when stopping workflow at 6 minutes: - codepen.io: 738 MB - Safari: 103 MB - Memory after waiting 5 minutes while workflow is stopped: - codepen.io: 671 MB (jumps to 710 MB briefly when focusing on the Safari window) - Safari: 91 MB These numbers are generally a little higher than the metrics for macOS 15.3.2/Safari 18.3.2 (could be due to environmental factors), but the great thing is that similar to macOS 15.3.2/Safari 18.3.2, the memory is apparently being recovered! 🎉 Looking good so far! Excited to try this out on iOS! Thank you so much, and take care! Kevin
Kevin
Comment 16 2025-12-16 07:58:01 PST
Hello there! 👋 From what I can tell, iOS 26.2 (released December 12, 2025) is the first GA release of iOS that has the fix. A co-worker of mine tested the CodePen reproduction in the OP on a device both before and after upgrading to iOS 26.2. Device: iPad Pro 12.9 2018 (4 GB of RAM) (specs: https://www.gsmarena.com/apple_ipad_pro_12_9_(2018)-9387.php ). - Uptime iOS 26.1 (in minutes): - 5:15 - 4:25 - 4:29 - 4:24 - 4:20 - 3:48 - Uptime after upgrading to iOS 26.2 (in minutes): - 60:00+ (stopped testing; no reload) - 150:00+ (stopped testing; no reload) Looking very solid! I really look forward to seeing the positive customer impact on this fix! You will be making so many people who take care of our infrastructure and communities very happy! Thank you so much again, Kimmo, and take care! Kevin
Note You need to log in before you can comment on or make changes to this bug.