当前位置:  开发笔记 > 编程语言 > 正文

getImageData - Web worker - 如何减少垃圾回收?

如何解决《getImageData-Webworker-如何减少垃圾回收?》经验,为你挑选了1个好方法。

我有一个示例web-worker画布更新脚本正在运行,但我注意到它每隔几秒就会停止大约200ms.通常的循环时间约为15ms.

我猜这是垃圾收集 - 它看起来像是分析器.

http://codepen.io/SarahC/pen/bgBoMM

我认为这是在这个功能:

function nextFrame(){
  timeChart.start();
  workersWorking = workerCount;
  var stripHeight = ~~( h / workerCount );
  for(var i = 0; i < workerCount; i++){
    var localImageData = ctx.getImageData(0, stripHeight * i, w, stripHeight); /// This needs putting in constant memory.... GC takes ages here.
    workers[i].postMessage({imageData: localImageData, YPosition: stripHeight * i, threadNumber: i});
  }
}

如果这个位正在制作所有的垃圾内存,我不知道我能做些什么来继续为这些数据块使用相同的内存区域.



1> Kaiido..:

传递imageData的缓冲区而不是imageData本身.

这样,您的缓冲区就会被传输(使用零复制操作),并且不会再污染主线程的内存.
否则,当您不传输它时,您的对象将被结构化克隆(就像您一样JSON.parse(JSON.stringify(yourObject));),这意味着当您从工作程序发送回主线程时,计算机将三个相同数据的副本保存在内存中.

请注意,当在worker中传递时,imageData的数据在主线程中不再可用(如果你尝试putImageData()它会抛出一个错误).遗憾的是我不知道改变ImageData缓冲区的好方法,但是你可以在创建时设置一个缓冲区,这要归功于ImageData()构造函数(显然在IE中仍然不支持...),这确实只是创建一个指针到arrayBuffer.

所以当支持所有这些时,只{width:XXX, height:XXX}创建ImageData结构(基本上是一个对象)而不是重缓冲区.其他所有东西都被移动了,不会污染记忆.

let workerURL = URL.createObjectURL(new Blob([workerScript.textContent], {
  type: 'application/javascript'
}));

const worker = new Worker(workerURL);
worker.onmessage = e => {
  let buf = e.data,
    arr = new Uint8ClampedArray(buf),
    processedImageData;
  try {
    processedImageData = new ImageData(arr, imageData.width, imageData.height);
  } catch (e) {
    processedImageData = ctx.createImageData(imageData.width, imageData.height);
    processedImageData.data.set(arr);
  }
  // checks that we didn't created an useless buffer in this last step
  // IE will because it doesn't support new ImageData(buf)
  console.log('Does our TypedArray share the same buffer as the one we received ? ',
              arr.buffer === buf);
  console.log('Does our new imageData share the same buffer as the one we received ? ',
              processedImageData.data.buffer === buf);
  // Note that here a check for the original imageData's buffer has no sense
  //       since it has been emptied
  ctx.putImageData(processedImageData, 0, 0);
}

const ctx = canvas.getContext('2d');
ctx.fillStyle = 'green';
ctx.fillRect(20, 20, 60, 80);
let imageData = ctx.getImageData(0, 0, 300, 150);
// pass it as transferable
worker.postMessage(imageData.data.buffer, [imageData.data.buffer]);
console.log(imageData.data.length, 'now empty')

推荐阅读
黄晓敏3023
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有