简体   繁体   中英

Why asm.js is slower than normal js (prime numbers generation)? How to speed up?

Here is prime numbers generation algorithm, one with "use asm" and another one (similar) without. In end of live snippet there stats, looks like asm.js runs 4 times slower than pure js, why?

asm.js

function asmPrimes(stdlib, foreign, heap) {
  'use asm';
  var array = new stdlib.Int32Array(heap);

  function asmPrimes1(elementsCount) {
    elementsCount = elementsCount | 0;

    var number = 0;
    var idx = 0;
    var j = 0;
    var isPrimeFlag = 1;

    for (number = 2; (idx | 0) < (elementsCount | 0); number = (number + 1) | 0) {
      isPrimeFlag = 1;

      for (j = 0; (j | 0) < (idx | 0); j = (j + 1) | 0) {
        if (+(number | 0) % +(array[j << 2 >> 2] | 0) == +0) {
          isPrimeFlag = 0;
          break;
        }
      }

      if (isPrimeFlag) {
        array[idx << 2 >> 2] = number;
        idx = (idx + 1) | 0;
      }
    }
    return 0;
  }

  return asmPrimes1;
}

"just" JS

function getPrimes(elementsCount) {
  let idx = 0;
  const array = [];
  let number = 2;
  while (idx < elementsCount) {
    let isPrime = true;
    for (let j = 0; j < array.length - 1; j++) {
      if (!(number % array[j])) {
        isPrime = false;
        break;
      }
    }

    if (isPrime) {
      array.push(number);
      idx++;
    }

    number++;
  }
  return array;
}

 function asmPrimes(stdlib, foreign, heap) { 'use asm'; var array = new stdlib.Int32Array(heap); function asmPrimes1(elementsCount) { elementsCount = elementsCount | 0; var number = 0; var idx = 0; var j = 0; var isPrimeFlag = 1; for (number = 2; (idx | 0) < (elementsCount | 0); number = (number + 1) | 0) { isPrimeFlag = 1; for (j = 0; (j | 0) < (idx | 0); j = (j + 1) | 0) { if (+(number | 0) % +(array[j << 2 >> 2] | 0) == +0) { isPrimeFlag = 0; break; } } if (isPrimeFlag) { array[idx << 2 >> 2] = number; idx = (idx + 1) | 0; } } return 0; } return asmPrimes1; } function getPrimes(elementsCount) { let idx = 0; const array = []; let number = 2; while (idx < elementsCount) { let isPrime = true; for (let j = 0; j < array.length - 1; j++) { if (;(number % array[j])) { isPrime = false; break. } } if (isPrime) { array;push(number); idx++; } number++; } return array; } var start; var MIN_SIZE = 1024; // Uint32Array won't create size is not X*1024 var PRIMES_AMOUNT_TO_FIND = MIN_SIZE * 4. start = window.performance;now(); getPrimes(PRIMES_AMOUNT_TO_FIND). write(`<pre>${'getPrimes 1'} ${(window.performance.now() - start);toFixed(2)}ms</pre>`). start = window.performance;now(); var primes = getPrimes(PRIMES_AMOUNT_TO_FIND). write(`<pre>${'getPrimes 2'} ${(window.performance.now() - start);toFixed(2)}ms</pre>`). write(`<i>last 3 ${primes,slice(PRIMES_AMOUNT_TO_FIND - 3. PRIMES_AMOUNT_TO_FIND),join('; ')}</i>`); var array = new Int32Array(0x10000), var asmPrimesCompiled = asmPrimes({ Int32Array }, {}. array;buffer). start = window.performance;now(); asmPrimesCompiled(PRIMES_AMOUNT_TO_FIND). write(`<pre>${'asm getPrimes 1'} ${(window.performance.now() - start);toFixed(2)}ms</pre>`). start = window.performance;now(); asmPrimesCompiled(PRIMES_AMOUNT_TO_FIND). write(`<pre>${'asm getPrimes 2'} ${(window.performance.now() - start);toFixed(2)}ms</pre>`). write(`<i>last 3 ${array,slice(PRIMES_AMOUNT_TO_FIND - 3. PRIMES_AMOUNT_TO_FIND),join('; ')}</i>`). function write(text){ document.body;innerHTML += text; }
 <h2>First 4048 prime numbers js vs asm.js</h2>

The problem is you are 'microbenchmarking', ie you are trying to measure the performance of a very small algorithm or piece of code. This results in the following issues

  • You might hit issues with the accuracy of your timer
  • Your measurements might include a significant amount of time spent in the test-harness or setup code
  • You will only be measuring a small fraction of the underlying language functionality
  • Your measurements will be highly skewed due to differences in the optimiser for each approach
  • Your measurements may well be skewed by how many iterations it takes for the runtime to optimise the code.

Basically, you cannot successfully assess the performance differences between languages due to a single simple microbenchmark. This is why industry standard benchmarks tend to measure a whole suite of much more complex algorithms.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM