是否有可能在浏览器中发现类型化的数组分配限制?

时间:2015-03-17 23:02:53

标签: javascript google-chrome memory-management browser typed-arrays

尝试使用内存池预分配,我发现分配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,但我想弄清楚我能尝试的最大合理池分配而不会破坏我的标签。

1 个答案:

答案 0 :(得分:0)

像这样填充一个大缓冲区需要一些时间,并且可能会阻止浏览器,直到Chrome说得足够。

您需要将其分解为块,以便浏览器可以偶尔屏蔽一下。这将需要异步方法。

除此之外:即使浏览器具有任意内存限制,即使填充时间很短,也不会使选项卡崩溃。如果内存用完了分页将由系统调用,所以在这里应该没有太大的问题(更慢,但可用)。如果它仍然与下面的解决方案崩溃,我会说这将是一个错误(考虑然后报告给crbug.com)。

以下是异步填充大缓冲区的一种方法:

&#13;
&#13;
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;
&#13;
&#13;