尝试使用内存池预分配,我发现分配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,则为100%(例如,尝试在控制台中获取bigArray.length,记录它,或者更糟糕的是,将鼠标悬停在其上以查看其内容)。
在现代浏览器(主要是Firefox和Chrome)中有没有办法(非标准的,复杂的)来计算分配限制?我想在极限附近预先分配一个池,并使用该池来满足我后续浮点数组的所有需求 - 我不是非常需要分配一个60M的Float32Array,但我想弄清楚我能尝试的最大合理池分配而不会破坏我的标签。
答案 0 :(得分:0)
像这样填充一个大缓冲区需要一些时间,并且可能会阻止浏览器,直到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;
});
}
&#13;
<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>
&#13;