我做了一个非常简单的基准测试程序,用4种不同的语言计算出10000000以内的所有质数。在
以上是平均每次运行3次,用户时间
在节点.js跑得最快。这让我感到困惑有两个原因:
我用-O2优化编译了c代码,但是我尝试了所有级别的优化,结果没有产生明显的差别。在
"use strict";
var isPrime = function(n){
//if (n !== parseInt(n,10)) {return false};
if (n < 2) {return false};
if (n === 2) {return true};
if (n === 3) {return true};
if (n % 2 === 0) {return false};
if (n % 3 === 0) {return false};
if (n % 1) {return false};
var sqrtOfN = Math.sqrt(n);
for (var i = 5; i <= sqrtOfN; i += 6){
if (n % i === 0) {return false}
if (n % (i + 2) === 0) {return false}
}
return true;
};
var countPrime = function(){
var count = 0;
for (let i = 1; i < 10000000;i++){
if (isPrime(i)){
count++;
}
}
console.log('total',count);
};
countPrime();
#include <stdio.h>
#include <math.h>
#define true 1
#define false 0
int isPrime (register long n){
if (n < 2) return false;
if (n == 2) return true;
if (n == 3) return true;
if (n % 2 == 0) return false;
if (n % 3 == 0) return false;
if (n % 1) return false;
double sqrtOfN = sqrt(n);
for (long i = 5; i <= sqrtOfN; i += 6){
if (n % i == 0) return false;
if (n % (i + 2) == 0) return false;
}
return true;
};
int main(int argc, const char * argv[]) {
register long count = 0;
for (register long i = 0; i < 10000000; i++){
if (isPrime(i)){
count++;
}
}
printf("total %li\n",count);
return 0;
}
$ gcc primeCalc.c -lm -g -O2 -std=c99 -Wall
$ time ./a.out
total 664579
real 0m6.718s
user 0m6.668s
sys 0m0.008s
公共类PrimeCalc{
public static void main(String[] args) {
long count = 0;
for (long i = 0; i < 10000000; i++){
if (isPrime(i)){
count++;
}
}
System.out.println("total "+count);
}
public static boolean isPrime(long n) {
if (n < 2) return false;
if (n == 2) return true;
if (n == 3) return true;
if (n % 2 == 0) return false;
if (n % 3 == 0) return false;
if (n % 1 > 0) return false;
double sqrtOfN = Math.sqrt(n);
for (long i = 5; i <= sqrtOfN; i += 6){
if (n % i == 0) return false;
if (n % (i + 2) == 0) return false;
}
return true;
};
}
$ javac PrimeCalc.java
$ time java PrimeCalc
total 664579
real 0m7.197s
user 0m7.036s
sys 0m0.040s
$ java -version
java version "1.7.0_111"
OpenJDK Runtime Environment (IcedTea 2.6.7) (7u111-2.6.7-0ubuntu0.14.04.3)
OpenJDK 64-Bit Server VM (build 24.111-b01, mixed mode)
import math
def isPrime (n):
if n < 2 : return False
if n == 2 : return True
if n == 3 : return True
if n % 2 == 0 : return False
if n % 3 == 0 : return False
if n % 1 >0 : return False
sqrtOfN = int(math.sqrt(n)) + 1
for i in xrange (5, sqrtOfN, 6):
if n % i == 0 : return False;
if n % (i + 2) == 0 : return False;
return True
count = 0;
for i in xrange(10000000) :
if isPrime(i) :
count+=1
print "total ",count
time python primeCalc.py
total 664579
real 0m46.588s
user 0m45.732s
sys 0m0.156s
$ python --version
Python 2.7.6
$ uname -a
Linux hoarfrost-node_6-3667558 4.2.0-c9 #1 SMP Wed Sep 30 16:14:37 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
(6.66 s)优化2,gcc primeCalc.c-lm-O2-std=c99-Wall
我在这里读到了这篇文章: Why is this NodeJS 2x faster than native C? 这段代码使用了一个没有实际意义的示例。就好像编译器可以在编译时计算出结果一样,它甚至不需要执行100000000次循环就可以得到答案。 如果在计算中再增加一个除法步骤,那么优化的意义就小得多。在
for (long i = 0; i < 100000000; i++) {
d += i >> 1;
d = d / (i +1); // <-- New Term
}
更新03/15/2017 在阅读了@leon的答案后,我做了一些验证测试。在
测试1-32位Beaglebone Black,664579素数最高10000000
未编辑加州时间.js以及运行在Beaglebone black上的CalcTime.c,它有一个32位处理器。在
测试2-64位Macbook Pro,664579 prime最高10000000
用uint32替换calcPrime.c代码中的长数据类型,并在我的MacBookPro上运行,它有一个64位处理器。在
测试3-64位Macbook Pro,91836个素数(i=1;i<;800000000;i+=10000)
在C代码中使用无符号长数据类型,强制javascript使用一些64位。 -C代码=20.4秒(叮当声,长数据类型) -JS代码=17.8秒(节点v4)
测试4位64位Macbook Pro,86277个素数(i=8000,00001;i<;1600000000;i+=10000)
在C代码中使用无符号长数据类型,强制javascript使用所有64位。 -C代码=35.8秒(叮当声,长数据类型) -JS代码=34.1秒(节点v4)
测试5-Cloud9 64位Linux,(i=0;i<;10000000;i++)
language datatype time % to C
javascript auto 3.22 31%
C long 7.95 224%
C int 2.46 0%
Java long 8.08 229%
Java int 2.15 -12%
Python auto 48.43 1872%
Pypy auto 9.51 287%
测试6-Cloud9 64位Linux,(i=800000001;i<;1600000000;i+=10000)
javascript auto 52.38 12%
C long 46.80 0%
Java long 49.70 6%
Python auto 268.47 474%
Pypy auto 56.55 21%
(所有结果均为平均值三次运行的用户秒数,运行之间的时间变化<;10%)
混合结果
在整数范围内将C和Java数据类型更改为integer可以显著加快执行速度。在BBB和Cloud9上,转换到ints的C比节点.js. 但在我的Mac上节点.js程序仍然运行得更快。也许是因为Mac使用的是clang,BBB和cloud9计算机使用的是gcc。有人知道gcc编译的程序比gcc快吗?在
当使用所有64位整数时,C比节点.js在BBB和Cloud9电脑上,但在我的MAC电脑上慢一点。在
在这些测试中,您还可以看到pypy的速度大约是标准python的四倍。在
事实上节点.js甚至与C兼容也让我吃惊。在
我花了几天时间研究JS/V8和C之间的性能差异,首先关注V8引擎产生的氢IR。然而,在确保没有特别的优化存在之后,我又回到了对汇编输出的分析中,我突然发现答案非常简单,归结到Jay Conrod's blog post中关于V8内部结构的几句话:
本例允许在32位和节点.js充分利用这一点!C代码使用
long
类型,在OP(以及我的)平台上,它恰好是一个64位类型。因此,这是一个32位算术vs 64位算术问题,主要是由于昂贵的除法/余数运算。在如果C代码中的
long
被int
替换,那么gcc生成的二进制文件将跳动节点.js. 在另外,如果循环是为了在32位数字范围之外的范围内查找素数,则节点.js版本明显下降。在
证据
使用的源代码可以在答案中找到,在结果下面。在
从第一列中包含的数字开始计算长度为100000的素数:
^{pr2}$计数_素描.js
计算素数c
相关问题 更多 >
编程相关推荐