【问题标题】:Web Worker Creating GarbageWeb Worker 创建垃圾
【发布时间】:2017-03-12 22:17:25
【问题描述】:

我正在开发一个使用网络工作者的项目。似乎工人正在产生相当多的额外垃圾,必须从消息传递中收集。

我正在通过主线程的 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}});

【问题讨论】:

  • 有多少工人?有多少不同的行星被操纵?这似乎是一个很有希望的起点:nolanlawson.com/2016/02/29/high-performance-web-worker-messages
  • 我有两个工人,一个用于 9 个行星,然后以同样的方式处理更多的小行星。现在我只是想弄清楚如何用 1 名工人来处理垃圾。
  • 那篇文章读得很好,我一定会试试看的。不过,它似乎不会减少复制带来的垃圾。我认为 arraybuffer 可能会有所帮助,但不确定我是否可以将它与对象属性一起使用?
  • 如果你想要零分配消息,你需要SharedArrayBuffer。如果你想要低分配开销,你需要将 arraybuffers 作为 transferable 参数传递,并在它们被发回时回收它们。
  • 无论如何,如果您考虑到每秒有 60 帧并且消息传递可能涉及内部字符串化,那么 6MB/s 并不算多。所以即使一切都是最优的,你仍然会期望几十 KB/s

标签: javascript garbage-collection garbage


【解决方案1】:

我尝试了两种不同的途径,最终将它们结合使用。首先,在我发送一些元素之前,我使用 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]);

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

// 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 发送,而不会产生一堆额外的垃圾。我认为这里最好的方法是将数组发送给工作人员并将其留在那里,然后返回更新的位置。仍在努力。

【讨论】:

    猜你喜欢
    • 2016-04-21
    • 1970-01-01
    • 1970-01-01
    • 2012-01-06
    • 1970-01-01
    • 2013-07-20
    • 1970-01-01
    • 1970-01-01
    • 2019-03-03
    相关资源
    最近更新 更多