After trying to understand why some of my Web application's objects were retained in memory by Chrome I think I may have narrowed it down to a case of a MediaRecorder
object being retained by the browser even though the application has let go of all references to it, explicit and implicit.
Please observe the following minimal example that reproduces the issue:
new MediaRecorder(new MediaStream())
After evaluating the above expression -- a MediaRecorder
object being created with no references (variables or properties) to it being assigned -- I profiled the heap usage using the Memory tab in both Chrome and Chromium, and the presence of the MediaRecorder
object on the heap isn't transient -- the object is there for as long as I care to locate it on the heap. It doesn't disappear.
Why is it retained? Testing with a trivial class like Object
instead -- evaluating new Object()
, for example, behaves as expected -- garbage collection eventually collects the anonymous object. But not so with MediaRecorder
. This smells an awful lot like a bug to me.
Firefox, in comparison, releases the MediaRecorder
object in due time, considering the garbage collection of course, at least it isn't even on the heap seconds after I execute the statement above, not when I take the snapshot of it.
The media recorder object is not referenced by anything and should have the shortest lifetime it may ever have, yet it is there in memory afterwards in the snapshot I take after the console is cleared (the developers behind Developer Tools for Chrome recommend clearing the console before taking a heap snapshot because the former may hold on to objects that otherwise would be released).
I can't find any methods in the MediaRecorder
class that would indicate to me one can disassociate it from a stream or otherwise "close" it. Short of making sure there are no obvious or not-so-obvious (e.g. through event listeners) references to it, I can only hope that an anonymous object isn't retained, and such objects usually aren't, but MediaRecorder
objects seem to be. There doesn't seem to exist any lever for me to pull to dispose of one, so to speak.
You can see in the screenshot below that what objects retain the media recorder aren't exactly part of my scripts, they rather seem to be related to some internal browser state:
The window icon next to the object selected in the "Constructor" column has the tooltip "User object [is] reachable from window". The snippet above is the only code I run in the tab, why would the object be "reachable from window", and if it is, it surely cannot be any references I manage?
So why is the object retained? The bigger problem here is that if my application initiates many recordings and creates a new media recorder object for each, these objects will just keep piling up in memory, a de-facto case of memory leaking.
Like I said, I ran the same statement in Firefox 62.0.2 and there the behavior is as I would expect -- the single MediaRecorder
object I created seems to go out of scope (as it should being how it should have no references to it) shortly after it is created.
(Chrome version 69.0.3497.100, x64 on Windows 10)