这是素数生成算法,一个带有“use asm”,另一个(类似)没有。 在实时片段末尾有统计数据,看起来 asm.js 的运行速度比纯 js 慢 4 倍,为什么?
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;
}
“只是”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>
最佳答案
问题是您正在进行“微基准测试”,即您正在尝试测量非常小的算法或代码段的性能。这会导致以下问题
- 您可能会遇到计时器准确性问题
- 您的测量可能包括在测试工具或设置代码上花费的大量时间
- 您将仅测量底层语言功能的一小部分
- 由于每种方法的优化器存在差异,您的测量结果将存在很大偏差
- 您的测量结果很可能会因运行时优化代码所需的迭代次数而产生偏差。
基本上,由于单个简单的微基准测试,您无法成功评估语言之间的性能差异。这就是为什么行业标准基准测试倾向于测量一整套更复杂的算法。
关于javascript - 为什么asm.js比普通js(素数生成)慢?如何加快速度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58991721/