JavaScript的:内存不足在阿特实施筛巨大成绩阵列([removed] Out of Memo

2019-10-29 13:10发布

目前我正在运行JavaScript,asm.js和WebAssembly之间的一些基准。 为此,我已经实现了一个小程序,搜索与阿特金的筛算法素数。

为了使斜坡上升可以忽略不计,我计算的素数高达500'000'000。 我的问题是,JavaScript实现内存用完,因为结果阵列变得庞大。

这就是我目前的执行情况:

const AMOUNT = 500000000;

function getPrimes() {
  const limit = AMOUNT;
  const width = Math.sqrt(limit);
  let i, j, x, y, z;
  let primes = new Array(limit);

  const begin = performance.now();
  for (x = 1; x <= width; x++) {
    for (y = 1; y <= width; y++) {
      z = 4 * x * x + y * y;
      if (z < limit && (z % 60 == 1 || z % 60 == 13 || z % 60 == 17 || z
          % 60 == 29 || z % 60 == 37 || z % 60 == 41 || z % 60 == 49
          || z % 60 == 53)) {
        primes[z] = !primes[z];
      }

      z = 3 * x * x + y * y;
      if (z < limit && (z % 60 == 7 || z % 60 == 19 || z % 60 == 31 || z
          % 60 == 43)) {
        primes[z] = !primes[z];
      }

      z = 3 * x * x - y * y;
      if (x > y && z < limit && (z % 60 == 11 || z % 60 == 23 || z % 60
          == 47 || z % 60 == 59)) {
        primes[z] = !primes[z];
      }
    }
  }

  const end = performance.now();

  let last_prime = 0;
  for (i = limit; i >= 0; i--) {
    if(primes[i] == 1) {
      last_prime = i;
      break;
    }
  }

  primes = null;
  time_spent = end - begin;
  console.log(time_spent/1000 + ', ' + last_prime);
}

document.addEventListener("DOMContentLoaded", function() {
  let i;
  for (i = 0; i <= 10; i++) {
    getPrimes();
  }
});

这是我的HTML来运行它:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Find Primes</title>
    <script src="./find-primes.js"></script>
  </head>
  <body>
    Check the console.
  </body>
</html>

我试过到目前为止: -确保primes后分别由废掉它运行数组被收集。 - 分配一旦整个阵列。

你有更多的想法,以优化我的JavaScript实现的内存使用情况?

我试图阻止的,分裂阵列或计算结果不同的迭代,因为我想基准的原始计算性能。 不应该有在测试任何影响的内存管理。

我正在使用:

  • 谷歌浏览器:版本75.0.3770.90(正式版本)(64位)
  • Mozilla Firefox浏览器:版本67.0.2(64位)

先感谢您!

Answer 1:

取而代之的Array ,其天真地存储每个标志的为double (也可能有其存储任意混合类型的能力,甚至更多的内存开销),你可以使用一个Uint8Array ,或其他无符号整数格式,它会通过减少你的内存使用情况至少64倍。

你需要修改你如何初始化,切换,虽然检查标志。

初始化:

const BitArray = Uint8Array; // or Uint16Array, Uint32Array
const BITS_PER_ELEMENT = BitArray.BYTES_PER_ELEMENT * 8;
const BIT_SHIFT = Math.log2(BITS_PER_ELEMENT);
const BIT_MASK = BITS_PER_ELEMENT - 1;
let primes = new BitArray(Math.ceil(limit / BITS_PER_ELEMENT));

切换:

primes[z >> BIT_SHIFT] ^= 1 << (z & BIT_MASK);

检查:

if (primes[i >> BIT_SHIFT] & (1 << (i & BIT_MASK)))

之间的任何选择Uint8ArrayUint16ArrayUint32Array将使用的存储器中的相同的量。



文章来源: JavaScript: Out of Memory for huge result array in Sieve of Atkin implementation