【问题标题】:JavaScript performance when handling large arrays处理大型数组时的 JavaScript 性能
【发布时间】:2013-08-21 19:11:44
【问题描述】:

我目前正在用 JavaScript 编写一个图像编辑程序。我选择 JS 是因为我想了解更多。我正在处理的平均图像大小约为 3000 x 4000 像素。当转换为 imageData(用于编辑像素)时,我必须处理多达 48000000 个值。这就是为什么我决定引入网络工作者并让他们只编辑数组的第 n 部分。假设我有十个网络工作者,每个工作者将不得不处理 4800000 个值。 为了能够使用网络工作者,我将大数组通过我选择的线程数量进行划分。我使用的这段代码如下所示:

while(pixelArray.length > 0){
    cD.pixelsSliced.push(pixelArray.splice(0, chunks)); //Chop off a chunk from the picture array
}

在工作人员对数组进行处理后,他们将其保存到另一个数组中。每个工人都有一个 ID,并将他的部分保存在提到的数组中他的 ID 位置(以确保数组保持正确的顺序)。我使用 $.map 将该数组(看起来像 [[1231][123213123][213123123]] 连接到一个大数组 [231231231413431] 中,稍后我将从中创建我需要的 imageData。它看起来像这样:

cD.newPixels = jQuery.map(pixelsnew, function(n){
    return n;
});

创建此数组 (cD.pixelsSliced) 后,我创建 imageData 并将此图像复制到 imageData-Object 中,如下所示:

cD.imageData = cD.context.createImageData(cD.width, cD.height);
for(var i = 0; i < cD.imageData.data.length; i +=4){ //Build imageData
    cD.imageData.data[i + eD.offset["r"]] = cD.newPixels[i + eD.offset["r"]];
    cD.imageData.data[i + eD.offset["g"]] = cD.newPixels[i + eD.offset["g"]];
    cD.imageData.data[i + eD.offset["b"]] = cD.newPixels[i + eD.offset["b"]];
    cD.imageData.data[i + eD.offset["a"]] = cD.newPixels[i + eD.offset["a"]];
}

现在我确实意识到我在这里处理大量数据并且我可能不应该使用浏览器进行图像编辑,而是使用不同的语言(我在 uni 中使用 Java)。但是我想知道您是否对性能有任何提示,因为坦率地说,当我第一次尝试大图像时,我感到非常惊讶。我没有想到,加载图像需要“那么长”的时间(代码的第一次和平)。 Firefox 实际上认为我的脚本已损坏。其他两部分代码是我发现会减慢脚本速度的部分(这是正常的)。所以是的,我会感谢任何提示。

谢谢

【问题讨论】:

  • 不要在包含 4800 万个项目的数组上使用 'jQuery.map' 之类的东西。这太荒谬了。另外,忘记网络工作者,因为他们不仅需要复制,还需要序列化。直接在 main/ui 线程中循环遍历数组会快 10000 倍。
  • 例如jsfiddle.net/VjZnn/1 150 毫秒将每个值增加 1。将该数组序列化为 json 以将其传递给网络工作者需要数年时间
  • 我建议使用 jsperf.com 来调整和测试你的变化

标签: javascript html performance image-processing web-worker


【解决方案1】:

我建议在使用 Web Workers 时研究可转移对象而不是结构化克隆。 Web Worker 通常使用结构化克隆来传递对象,换句话说就是制作了一个副本。对于大型对象(例如大型图像),这可能会花费大量时间。

使用 Transferable Objects 时,数据会从一个上下文传输到另一个上下文。换句话说,零拷贝,应该会提高向 Worker 发送数据的性能。

更多信息请查看: http://www.w3.org/html/wg/drafts/html/master/infrastructure.html#transferable-objects

另外,另一个想法可能是将拆分和对接大数组的任务转移到网络工作者身上。 只是在这里进行头脑风暴,但是,也许您可​​以先生成一个 Web Worker,我们称它为 Mother Worker。该工人可以拆分阵列,然后生成 10 个其他执行繁重任务的子工人并将其送回给他们的母亲。

母亲最终将所有内容重新组合在一起并发送回主应用程序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-10
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 2020-07-06
    • 2013-10-25
    相关资源
    最近更新 更多