gpt4 book ai didi

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

转载 作者:搜寻专家 更新时间:2023-11-01 05:20:48 25 4
gpt4 key购买 nike

我有一个正在运行的网络工作人员 Canvas 更新脚本示例,但我注意到它每隔几秒就会停顿大约 200 毫秒。通常的循环时间约为 15 毫秒。

我猜这是垃圾回收——从分析器看来是这样。

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});
}
}

如果是这个位造成了所有的垃圾内存,我不知道我能做些什么来为这些数据 block 继续使用相同的内存区域。

最佳答案

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

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

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

所以当所有这些都被支持时,只有 ImageData 结构(基本上是一个对象 {width:XXX, height:XXX})被创建而不是一个沉重的缓冲区。其他一切都只是移动,不会污染内存。

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')
<script type="worker-script" id="workerScript">
self.onmessage = e => {
let buf = e.data,
arr = new Uint8Array(buf);
console.log('worker received', buf);
for(let i =0; i<arr.length; i+=4){
arr[i] = (arr[i] + 128) % 255;
arr[i+1] = (arr[i+1] + 128) % 255;
arr[i+2] = (arr[i+2] + 128) % 255;
}
self.postMessage(buf, [buf]);
// this won't print in stacksnippet's console
// you have to check your dev tools' one
console.log('worker now holds', buf.byteLength, 'empty');

};
</script>
<canvas id="canvas"></canvas>

还有一个使用结构克隆的反例:

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

const worker = new Worker(workerURL);
worker.onmessage = e => {
let buf = e.data;
// so our original imageData's arrayBuffer is still available
imageData.data.set(buf);
// Here we can check for equality with the first arrayBuffer
console.log('Is the first bufferArray the same as the one we received ?', imageData.data.buffer === buf);
ctx.putImageData(imageData, 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);
console.log(imageData.data.length, 'not empty')
<script type="worker-script" id="workerScript">
self.onmessage = e => {
let buf = e.data,
arr = new Uint8Array(buf);
console.log('worker received', buf);
for(let i =0; i<arr.length; i+=4){
arr[i] = (arr[i] + 128) % 255;
arr[i+1] = (arr[i+1] + 128) % 255;
arr[i+2] = (arr[i+2] + 128) % 255;
}
console.log(arr);
self.postMessage(buf);
// this won't print in stacksnippet's console
// you have to check your dev tools' one
console.log('worker now holds', buf.byteLength, 'full');
};
</script>
<canvas id="canvas"></canvas>

关于javascript - getImageData - Web worker - 如何减少垃圾回收?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41722068/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com