flutter / devtools

Performance tools for Flutter
https://flutter.dev/docs/development/tools/devtools/
BSD 3-Clause "New" or "Revised" License
1.58k stars 324 forks source link

Heap snapshot uses order of magnitude more memory than actual heap size #6144

Open bkonyi opened 1 year ago

bkonyi commented 1 year ago

While attempting to debug a memory issue in a relatively simple application using heap snapshot diffing, I encountered some DevTools crashes while attempting to take the second snapshot.

I opened Chrome DevTools and saw the following stats in the memory page:

Before snapshot: image

After snapshot (147.4 MiB heap): image

After second snapshot attempt (tab crashes at 4GiB after hitting 64-bit Chrome's memory limit): image

This order of magnitude overhead after processing a heap snapshot makes the snapshot diffing tool unusable in the web version of DevTools, even when examining relatively small heaps.

polina-c commented 1 year ago

I tested it with gallery (that is relatively complicated) and I could take 10 snapshots before crashing.

Yes, we can add optimization at cost of code simplicity and user experience, but there still will be applications that will cause crash, because other platforms allow much bigger memory consumption than Chrome tab.

I suggest to start showing warning that DevTools can reach chrome memory limit and instruct to either delete existing snapshots or to switch to macos version of devtools.

Thoughts?

bkonyi commented 1 year ago

I just tested with gallery in debug mode as a MacOS desktop application and saw the following.

Before snapshot: image

After first snapshot: image

Crash after starting 5th snapshot (was at ~4000 MiB after 4 snapshots): image

This definitely isn't as bad as the other application I was attempting to debug, but their heap sizes are comparable (124 MiB vs 147 MiB) and the demo application is fairly simple. At the very least, there's something in the structure of the heap that is causing the analysis to explode in size that we should investigate. This might point us to areas in the analysis that could be made more memory efficient or processed lazily, which could help us reduce the memory impact of this feature. In particular, the demo application has ~22,500 small widgets making up a grid, as well as ~22,500-45,000 non-Flutter objects storing state for these smaller widgets.

If you want to reproduce the failure, you can run this project as a Flutter desktop application on MacOS, and just collect two heap snapshots (no need to interact with the application at all).

I do agree that it also might be worth showing a warning or disabling heap snapshot functionality (at least on the web where we have a hard memory limit) when the Dart heap is greater than a predetermined size (> ~500 MiB?). There's definitely applications we just won't be able to analyze with this functionality in a web browser, but we should make sure that we can handle most applications, especially those with reasonably sized heaps.

polina-c commented 1 year ago

Thank you for additional research. It may be that I am converting retaining path to string format too early. Will revisit.

polina-c commented 1 year ago