Robert C. Martin的中文博库贴了一篇文章:
三大编程语言的性能PK--Java, C/C++和Ruby。里面说Java比C++快一些,引来粉丝们攻击。印象中Java应该只在某些特定的情况下比C/C++快,所以对他的结果我也表示怀疑。下面我试图找出真相。
为了方便测试,我把代码调整了一下:第一不把数组初始化的时间计入(测试数据表明,这样对C++没有好处。)第二,循环中每次都去调用sqrt(max),其实是个循环常量,提取出来(测试数据表明影响不大),否则就变成编译器的优化能力比较了。第三,统计全部时间,而不是在循环中每次计时。
调整后的Java和C++代码分别如下。在我的机器上,Java版使用的时间为3.5秒,而C++版的为4.0秒。如果不做第一点改动,则时间分别是4.3秒和4.8秒;注意Java的Arrays.fill是以for循环实现的。如果把C++版本的赋值改为memset,时间也就是4.3秒。改成VC版本之后,C++的测试数据基本上没有什么变化。这里把代码也列上了。
不过以上C++版本全部是未优化过的 (Java前面确省已经使用了)。下面的代码在打开全部优化之后的时间分别是:
Cygwin 3.3 (使用g++ -O3选项)
VC 3.4 (使用release版本)
可见在这里C++还是比Java快一点点的。C++粉丝们可以睡个安稳觉了。
JAVA:
Cygwin/C++:
VC/C++:
为了方便测试,我把代码调整了一下:第一不把数组初始化的时间计入(测试数据表明,这样对C++没有好处。)第二,循环中每次都去调用sqrt(max),其实是个循环常量,提取出来(测试数据表明影响不大),否则就变成编译器的优化能力比较了。第三,统计全部时间,而不是在循环中每次计时。
调整后的Java和C++代码分别如下。在我的机器上,Java版使用的时间为3.5秒,而C++版的为4.0秒。如果不做第一点改动,则时间分别是4.3秒和4.8秒;注意Java的Arrays.fill是以for循环实现的。如果把C++版本的赋值改为memset,时间也就是4.3秒。改成VC版本之后,C++的测试数据基本上没有什么变化。这里把代码也列上了。
不过以上C++版本全部是未优化过的 (Java前面确省已经使用了)。下面的代码在打开全部优化之后的时间分别是:
Cygwin 3.3 (使用g++ -O3选项)
VC 3.4 (使用release版本)
可见在这里C++还是比Java快一点点的。C++粉丝们可以睡个安稳觉了。
JAVA:
public class GeneratePrimes {
public static double generate(int max) ...{
//long start = System.currentTimeMillis();
boolean sieve[] = new boolean[max];
Arrays.fill(sieve, true);
sieve[0] = false;
sieve[1] = false;
int maxsqrt = (int)Math.sqrt(max);
long start = System.currentTimeMillis();
for (int i = 2; i < maxsqrt; i++) ...{
if (sieve[i]) ...{
for (int j = 2*i; j < max; j+=i) ...{
sieve[j]= false;
}
}
}
return (System.currentTimeMillis() - start)/1000.0;
}
public static void main(String args[]) ...{
double time = 0.d;
for (int i=100000; i<=5000000; i+=100000) ...{
time += generate(i);
}
System.out.println(time);
}
}
...
public static double generate(int max) ...{
//long start = System.currentTimeMillis();
boolean sieve[] = new boolean[max];
Arrays.fill(sieve, true);
sieve[0] = false;
sieve[1] = false;
int maxsqrt = (int)Math.sqrt(max);
long start = System.currentTimeMillis();
for (int i = 2; i < maxsqrt; i++) ...{
if (sieve[i]) ...{
for (int j = 2*i; j < max; j+=i) ...{
sieve[j]= false;
}
}
}
return (System.currentTimeMillis() - start)/1000.0;
}
public static void main(String args[]) ...{
double time = 0.d;
for (int i=100000; i<=5000000; i+=100000) ...{
time += generate(i);
}
System.out.println(time);
}
}
...
Cygwin/C++:
#include <iostream>
#include <math.h>
#include <sys/time.h>
using namespace std;
double generate(int max) {
struct timeval start;
struct timezone tz;
//gettimeofday(&start, &tz);
bool *sieve = new bool[max];
for (int i=0; i<max; i++) sieve[i] = true;
//memset(sieve, 1, sizeof(bool) * max);
sieve[0] = false;
sieve[1] = false;
int maxsqrt = (int)sqrt(max);
gettimeofday(&start, &tz);
for (int n=2; n<maxsqrt; n++) ...{
if (sieve[n]) ...{
for (int j=2*n; j<max; j+=n)
sieve[j] = false;
}
}
struct timeval end;
gettimeofday(&end, &tz);
double startSecond = start.tv_usec/1000000.0;
double endSecond = (end.tv_sec - start.tv_sec) + end.tv_usec/1000000.0;
return endSecond - startSecond;
}
int main(int ac, char** av) {
double time = 0.0;
for (int i=100000; i<=5000000; i+=100000) ...{
time += generate(i);
}
cout << time << endl;
}
... ...
#include <math.h>
#include <sys/time.h>
using namespace std;
double generate(int max) {
struct timeval start;
struct timezone tz;
//gettimeofday(&start, &tz);
bool *sieve = new bool[max];
for (int i=0; i<max; i++) sieve[i] = true;
//memset(sieve, 1, sizeof(bool) * max);
sieve[0] = false;
sieve[1] = false;
int maxsqrt = (int)sqrt(max);
gettimeofday(&start, &tz);
for (int n=2; n<maxsqrt; n++) ...{
if (sieve[n]) ...{
for (int j=2*n; j<max; j+=n)
sieve[j] = false;
}
}
struct timeval end;
gettimeofday(&end, &tz);
double startSecond = start.tv_usec/1000000.0;
double endSecond = (end.tv_sec - start.tv_sec) + end.tv_usec/1000000.0;
return endSecond - startSecond;
}
int main(int ac, char** av) {
double time = 0.0;
for (int i=100000; i<=5000000; i+=100000) ...{
time += generate(i);
}
cout << time << endl;
}
... ...
VC/C++:
#include "stdafx.h"
#include <iostream>
#include <math.h>
#include <Windows.h>
using namespace std;
double generate(int max) {
unsigned int start, end;
bool *sieve = new bool[max];
//for (int i=0; i<max; i++) sieve[i] = true;
memset(sieve, 1, max*(sizeof(bool)));
sieve[0] = false;
sieve[1] = false;
double maxsqrt = sqrt((double)max);
start = GetTickCount();
for (int n=2; n<maxsqrt; n++) ...{
if (sieve[n]) ...{
for (int j=2*n; j<max; j+=n)
sieve[j] = false;
}
}
end = GetTickCount();
return (end - start)/1000.0;
}
int main(int ac, char** av) {
double time = 0.0;
for (int i=100000; i<=5000000; i+=100000) ...{
time += generate(i);
}
cout << time << endl;
} ... ...
#include <iostream>
#include <math.h>
#include <Windows.h>
using namespace std;
double generate(int max) {
unsigned int start, end;
bool *sieve = new bool[max];
//for (int i=0; i<max; i++) sieve[i] = true;
memset(sieve, 1, max*(sizeof(bool)));
sieve[0] = false;
sieve[1] = false;
double maxsqrt = sqrt((double)max);
start = GetTickCount();
for (int n=2; n<maxsqrt; n++) ...{
if (sieve[n]) ...{
for (int j=2*n; j<max; j+=n)
sieve[j] = false;
}
}
end = GetTickCount();
return (end - start)/1000.0;
}
int main(int ac, char** av) {
double time = 0.0;
for (int i=100000; i<=5000000; i+=100000) ...{
time += generate(i);
}
cout << time << endl;
} ... ...