17

在试图理解为什么我的一些 Web 应用程序的对象被 Chrome 保留在内存中之后,我想我可能已经把它缩小到MediaRecorder浏览器保留对象的情况,即使应用程序已经放弃了对它的所有引用,显式和隐含的。

请注意以下重现该问题的最小示例:

new MediaRecorder(new MediaStream())

在评估了上述表达式之后——MediaRecorder创建的对象没有分配给它的引用(变量或属性)——我使用 Chrome 和 Chromium 中的“内存”选项卡分析了堆使用情况,并且该MediaRecorder对象在堆上的存在是'不是瞬态的——只要我想在堆上定位它,对象就在那里。它不会消失。

为什么保留?使用类似的普通类进行测试——例如,Object评估的行为符合预期——垃圾收集最终会收集匿名对象。new Object()但不是这样MediaRecorder。这对我来说闻起来非常像虫子。

相比之下,FirefoxMediaRecorder在适当的时候释放对象,当然考虑到垃圾收集,至少在我执行上面的语句之后它甚至不在堆上,而不是在我拍摄它的快照时。

媒体记录器对象没有被任何东西引用,并且应该具有它可能拥有的最短生命周期,但它在我在控制台被清除后拍摄的快照中存在于内存中(Chrome 开发者工具背后的开发人员建议在之前清除控制台拍摄堆快照,因为前者可能会保留原本会被释放的对象)。

我在类中找不到任何可以MediaRecorder向我表明可以将其与流分离或以其他方式“关闭”它的方法。没有确保没有明显或不那么明显(例如通过事件侦听器)对它的引用,我只能希望匿名对象不会被保留,而这样的对象通常不会被保留,但MediaRecorder对象似乎是. 可以这么说,似乎没有任何杠杆可以让我拉动处理一个。

您可以在下面的屏幕截图中看到,保留媒体记录器的对象并不完全是我的脚本的一部分,它们似乎与某些内部浏览器状态有关:

Chrome 开发者工具中内存窗格的屏幕截图

在“构造函数”列中选择的对象旁边的窗口图标具有工具提示“用户对象 [is] 可从窗口访问”。上面的代码片段是我在选项卡中运行的唯一代码,为什么对象会“从窗口可访问”,如果是,它肯定不能是我管理的任何引用?

那么为什么要保留对象呢?这里更大的问题是,如果我的应用程序启动许多记录并为每个记录创建一个新的媒体记录器对象,这些对象将不断堆积在内存中,这实际上是内存泄漏的情况。

就像我说的,我在 Firefox 62.0.2 中运行了相同的语句,并且行为与我预期的一样——MediaRecorder我创建的单个对象似乎超出了范围(因为它应该没有引用它)创建后不久。

(Chrome 版本 69.0.3497.100,Windows 10 上的 x64)

4

3 回答 3

0

这被证实是 Chromium 的问题(暗示 Google Chrome 和可能的其他 Chromium 衍生产品,包括Electron):

https://bugs.chromium.org/p/chromium/issues/detail?id=899722

在撰写本文时,该问题被标记为“可用”,我认为这表明它已被确认并有效地等待有人介入并修复。

于 2021-02-22T11:58:55.320 回答
-2

根据规范

当一个 MediaStream 对象至少有一个尚未结束的 MediaStreamTrack 时,它就被认为是活动的。没有任何轨道或​​只有已结束轨道的 MediaStream 处于非活动状态。

当您创建一个新的 MediaStream 时,除非您停止其所有轨道,否则它将保持活动状态。

因此,要取消设置此对象,您需要显式删除其 MediaStreamTrack 对象,获取对流的引用,例如:

var myRecorder;
navigator.mediaDevices.getUserMedia({ 
  video: true,
  audio: true
}).then(function create_media_recorder(stream) {
  myRecorder = new MediaRecorder(stream);
  console.clear();
});

var myStream = myRecorder.stream;
myStream.getTracks().forEach(function(el) {
    el.stop()
}

之后,您应该会看到录制图标消失 - 媒体流现在处于非活动状态。

检查这些 API 以获得进一步的参考

https://developer.mozilla.org/en-US/docs/Web/API/MediaStream

https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack

于 2018-11-05T06:00:52.440 回答
-4

确保在浏览器的设置中未选中“在导航时保留日志”,否则 console.clear() 什么也不做。

https://developer.mozilla.org/en-US/docs/Web/API/Console/clear

编辑:

另外,我怀疑这是内存泄漏,因为无法访问的对象会被自动删除。MediaRecorder 更有可能将对象保存到全局范围。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management#Garbage_collection

“4.3.1 生命周期和媒体流”应该清楚一点。

https://www.w3.org/TR/mediacapture-streams/#stream-api

于 2018-10-31T09:41:34.117 回答