Web Worker 制造垃圾

Web Worker Creating Garbage

我正在从事一个利用网络工作者的项目。似乎工作人员正在生成相当多的额外垃圾,必须从消息传递中收集这些垃圾。

我正在通过来自主线程的 post 消息向工作人员发送三件事。第一个只是一个数字,第二个是一个有 7 个数字的数组,第三个是日期。前两个是对象的属性,如下所示。这在 RAF 上每 16 毫秒调用一次,用于大约 20 个对象。 GC 最终每 2 秒左右收集 12MB。我想知道是否有一种方法可以在不产生这么多垃圾的情况下做到这一点?感谢您的帮助!

        //planet num (property of object) is just a number like: 1

        //planetele looks like this (property of an object)
        //[19.22942, 313.4868, 0.04441, 0.7726, 170.5310, 73.9893, 84.3234] 

        //date is just the date object

        //posted to worker like so:

        planetWorker.postMessage({ 
            "planetnum": planet.num,
            "planetele": planet.ele,
            "date": datet
        });

        //the worker.js file uses that information to do calculations 
        //and sends back the planet number, with xyz coordinates. (4 numbers)

        postMessage({data: {planetnum : planetnum, planetpos: planetpos}});

我尝试了两种不同的方法,最后结合使用了它们。首先,在我发送一些元素之前,我使用 JSON.stringify 将它们转换为字符串,然后 JSON.parse 在将它们发送给工作人员后将它们取回。对于数组,我最终使用了可转移对象。这是我所做的一个简化示例:

var ast = [];

ast.elements = new Float64Array([0.3871, 252.2507, 0.20563, 7.005, 77.4548, 48.3305, 0.2408]);
ast.num = 1;

var astnumJ = JSON.stringify(ast.num); // Probably not needed, just example

// From main thread, post message to worker
asteroidWorker.postMessage({ 
    "asteroidnum": astnumJ,
    "asteroidele": ast.elements.buffer
},[ast.elements.buffer]);

这会将数组发送给 worker,它不会复制它,从而减少了产生的垃圾。它现在在主线程中不可访问,所以一旦 worker post 发送了消息,你必须将数组发送回主线程,否则它将不再作为 ast 的 属性 访问。在我的例子中,因为我有 20 - 30 个 ast 对象,我需要确保它们都通过 post 消息恢复了它们的元素,然后再调用它们的另一个更新。我在一个循环中用一个简单的计数器做了这个。

// In worker.js 
asteroidele = new Float64Array(e.data.asteroidele); // cast to type
asteroidnum = JSON.parse(e.data.asteroidnum); // parse JSON

// Do calculations with this information in worker then return it to the main thread

// Post message from worker back to main
self.postMessage({
    asteroidnum : asteroidnum, 
    asteroidpos : asteroidpos, // Calculated position with elements
    asteroidele : asteroidele // Return the elements buffer back to main
});

// Main thread worker onmessage function
asteroidWorker.onmessage = function(e){  
    var data1 = e.data;
    ast.ele = data1.asteroidele; // Restore elements back to ast object
}

不确定这是不是最好的方法,但它确实可以在不产生一堆额外垃圾的情况下将数组发送到 worker 或从 worker 接收到数组。我认为这里最好的方法是将数组发送给工作人员并将其留在那里,然后 return 更新位置。仍在努力。