通过内存池预分配实验,我发现分配 60M Float32Array 有时会导致浏览器选项卡崩溃(在 Chrome 中尝试过):
var bigArray = new Float32Array(60000000)
for (var i = 0; i < bigArray.length; i+=1) {
bigArray[i] = Math.random()
}
我在 8Gb 机器上总共分配了 240MB(即 Float32Array.BYTES_PER_ELEMENT * bigArray.length)。这使得选项卡崩溃的次数为 20%,如果我尝试检查 bigArray(例如,尝试在控制台中获取 bigArray.length、记录它,或者更糟糕的是,将鼠标悬停在它上面以查看其内容),则该选项卡崩溃的次数为 100%。
现代浏览器(主要是Firefox和Chrome)有没有一种方法(非标准的,随意复杂的)来计算分配限制?我想预先分配一个接近限制的池,并使用该池来满足我所有后续的浮点数组需求 - 我并不严格需要分配 60M Float32Array,但我想找出我可以尝试分配的最大合理池不会破坏我的标签。
像这样填充一个大缓冲区需要一些时间,并且可能会阻止浏览器,直到 Chrome 说足够。
您需要将其分解为块,以便浏览器可以偶尔喘口气。这将需要异步方法。
除此之外:即使浏览器有任意内存限制,即使填充需要很短的时间,它也不应该使选项卡崩溃。如果内存耗尽,系统将调用分页,因此这里也不会有太大问题(速度较慢,但可用)。如果使用下面的解决方案仍然崩溃,我会说这将是一个错误(然后考虑将其报告给 crbug.com)。
这是异步填充大缓冲区的一种方法:
function getFilledFloat32(size, callback) {
try {
var bigArray = new Float32Array(size), // allocate buffer
blockSize = 2 * 1024*1024, // 2mb blocks
block = blockSize, current = 0; // init block break and position
(function fill() {
while(current < size && block--)
bigArray[current++] = Math.random(); // fill buffer until end or block
if (current < size) { // was block
block = blockSize; // reset block-size
document.querySelector('span').innerHTML += "."; // !! just for demo
setTimeout(fill, 7); // wait 7ms, continue
}
else callback(bigArray) // we're done, invoke callback
})();
} catch(err) {
alert("Error: " + err.message);
}
}
// --- test code ----------------------------
var isBusy = false;
function fill() {
if (isBusy) return;
isBusy = true;
var mb = +document.getElementById("rngMem").value;
document.querySelector('span').innerHTML = "Filling.";
getFilledFloat32(mb * 1024*1024, function(buffer) {
alert("Done! First two indexes:\n" + buffer[0] + ",\n" + buffer[1]);
isBusy = false;
});
}
<label for="mem">Size in MB:</label>
<input id="rngMem" onchange="document.querySelector('output').value = this.value" type="range" min=10 max=500 value=60>
<output>60</output>
<button onclick="fill()">FILL</button>
<br><span></span>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)