如何真正关闭Web Worker,使浏览器释放占用的内存?

4
我计划做以下事情:
1. 启动一个worker。
2a. 这个worker必须加载一些巨大的数据(通过AJAX或importScripts),对其进行处理并获取结果,结果将保存在这个worker的变量中。
2b. 加载新的数据部分(必须替换先前的部分),对其进行处理并将所需的结果附加到变量中。
2c. ...等等。
3. 内存使用量会增加,因此我必须能够强制浏览器关闭该worker并“忘记”它。我会失去所有的数据,但可以摆脱内存损失。
4. 当我想要时,我会再次启动此worker。

我在便携式基于Chrome的浏览器中进行了测试(启用了--allow-file-access-from-files标志,否则Worker将无法启动):

app.html:

<!DOCTYPE html>
<html>
<head>
<title>Untitled</title>
<script src="jquery.js"></script>       
<script>
    $(function () {
        $('#click').on("click", function () {
            var w = new Worker('worker.js');
            w.onmessage = function (event) {
            console.log(event.data);
            };
            w.postMessage({
                "url": "hugedata1.js"
            });
            $('#click2').on("click", function () {
                w.postMessage({
                    "url": "hugedata2.js"
                });
            });
            $('#terminate').on("click", function () {
                w.terminate();
            });
        });
    });
</script>
</head>
<body>
<div id="click">start worker</div>
<div id="click2">load second portion of data</div>
<div id="terminate">terminate worker</div>
</body>
</html>  

worker.js:

var hugedataarr;
var myarr = [];
self.onmessage = function(event) {
    importScripts(event.data.url);
    myarr[myarr.length] = hugedataarr[0];
    self.postMessage(myarr);
}  

hugedata.js:

hugedataarr = [
{ "id": "1", "A": "b"}, 
//imagine millions of objects placed in here
{ "id": "5000000", "F": "g"}
]  

hugedata2.js:

hugedataarr = [
{ "id": "5000001", "H": "i"}, 
//imagine millions of objects placed in here
{ "id": "10000000", "X": "y"}
]  

请确保hugedata文件足够大,以便内存损失会立即显现。
步骤:1)打开“app.html”;2)点击“开始工作”,等待,检查控制台日志;3)点击“加载第二部分数据”,等待,检查控制台日志;4)点击“终止工作进程”或刷新页面;5)检查内存损失情况;6)重复步骤2-4以增加内存损失。
问题:如何真正关闭此工作进程,使其释放内存?或者如果不可能,如何真正刷新应用程序页面,让浏览器彻底“忘记”该工作进程并释放占用的内存?(因为按F5刷新页面无法解决内存问题)
1个回答

2
脚本本身只是运行并被丢弃;仅定义的结构和函数保留下来。在您的情况下,所有脚本所做的就是创建数组并将它们分配给变量hugedataarr。要使其中一个巨大数组消耗的内存可供垃圾回收,请执行以下操作(在您的工作程序中):
hugedataarr = undefined;

(或者= []如果你希望它始终指向一个数组,或者= /* 在此处添加任何其他内容 */。)

由于没有对巨大数组的进一步引用,引擎可以进行垃圾回收。是否以及何时执行取决于引擎。


但为什么Web Worker的终止不能让浏览器完全忘记它和它的数据,并立即释放其内存呢?实际上,我不能依赖GC:当内存消耗达到极限时,浏览器会冻结,但GC并没有完成它的工作,无论我做类似hugedataarr = nullhugedataarr = undefined之类的操作......我只想要绝对地刷新页面,以便UA认为是第一次打开它,或者完全关闭Web Worker及其所有数据,使得UA的内存使用水平与Worker启动之前相同! - lyrically wicked
@lyricallywicked:如果你使用的是任何一个好的引擎,GC会完成它的工作;除了整个页面刷新之外,你别无选择,只能依靠它。听起来你正在做一些事情来保留对巨大数组的引用,从而防止GC。 - T.J. Crowder
我来澄清一下。我甚至不关心GC,我关心的是我在上面评论中提出的问题:是否可能刷新页面,使浏览器的内存使用量与我第一次打开此页面时相同???按F5(简单位置重新加载)或worker.terminate()都没有帮助。 - lyrically wicked
2
@lyricallywicked:不,浏览器需要管理其内存池。如果你按F5键,你会刷新页面,之前页面的所有数据都可以被浏览器回收或重用;这已经不是一个JavaScript问题了。浏览器何时以及如何重用该内存,或将其释放回操作系统,完全取决于浏览器的实现。我相信Chrome的每个窗口一个进程模型使其立即在Chrome上发生;但上次我在这方面查看Firefox时,它更加复杂。 - T.J. Crowder
worker.terminate()怎么样?为什么它不能将内存使用量恢复到工作进程启动之前的状态?这是实现相关的吗? - lyrically wicked
1
@lyricallywicked:如果你在谈论F5没有发布它,那么这与JavaScript层完全无关,而与浏览器内存的管理有关。 - T.J. Crowder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接