This post has been republished via RSS; it originally appeared at: Microsoft Edge Blog.
Any sufficiently large web application will probably reach the point where it uses more memory than expected. At that point, a developer might start recording memory heap snapshots in DevTools to investigate what objects are contained in memory. For any object listed in the snapshot, DevTools shows, in the Retainers pane, what other objects cause it to remain in memory. Any object with no retainers can be discarded by the browser’s garbage collector, which reduces memory usage. However, the Retainers pane is only useful if it works correctly. Over the past several months, we have received several excellent bug reports from Microsoft Teams engineers describing cases where DevTools showed retainers that simply made no sense, and there was no way that a web application developer could take any action to remove those retainers. Thank you to everyone who brought these issues to our attention. We’ve fixed those bugs (details below), but of course there may be others, so if you see something that seems wrong, please speak up! The easiest way to get in touch is the feedback button in the devtools:
Swimming in false retainer paths
Suppose you were working on the Microsoft Edge new-tab page (edge://newtab) and wanted to know why the function namedobserve()
is being kept alive. You would hit F12 to open DevTools, navigate to the Memory tab, and select the relevant object in the top pane. In Microsoft Edge version 94, you would see four retainers for that function:

FeedbackVector
, an internal data type which collects data about what functions have been called by another function. Expanding that path a little more, you would see that the FeedbackVector
is owned by another function, HTMLElement.attachShadow()
:

observe()
. How can you possibly break that link, since it’s all V8 internals?
You can’t, which means there’s a bug. Either V8 is leaking memory, or the Retainers pane is incorrect, and both are serious high-priority issues for us. In this case, the problem was that Microsoft Edge showed incorrect retainers. We have fixed this issue in Microsoft Edge 99. Here is the correct answer list of retainers:

Keeping it fixed
It’s very important that developers can trust DevTools, so we are working on an automated solution to prevent regressions that introduce new false retainer paths. Based on the insight from Microsoft Teams that the heap snapshot needs to match the garbage collector’s marking behavior, we have proposed validation code that compares the outgoing edges for each node in the heap snapshot versus the objects visited by the actual garbage collection code and crashes the process if there is any mismatch. This validation will be included in debug builds (including those that we use for daily automated testing), so we can quickly find and fix any problems that cause a mismatch between the snapshot and the garbage collector’s behavior.Deoptimization data
Microsoft Teams engineers found that some large object graphs were retained by objects named “(code deopt data)”, like in the following screenshot:
Finalization registries
In yet another excellent report from Microsoft Teams, we saw that a bunch of FinalizationRegistry objects were retained directly by other FinalizationRegistries, and causing high memory usage: