基准C ++与Java,不切实际的结果
我做了一个简单的测试,我知道C ++更快但我的测试结果不切实际。
C ++代码是:
#include #include unsigned long long s(unsigned long long n) { unsigned long long s = 0; for (unsigned long long i = 0; i < n; i++) s += i; return s; } int main() { LARGE_INTEGER freq, start, end; QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&start); printf("%llu\n", s(1000000000)); QueryPerformanceCounter(&end); double d = (double) (end.QuadPart - start.QuadPart) / freq.QuadPart * 1000.0; printf("Delta: %f\n", d); return 0; }
Java代码是:
public class JavaApplication5 { public static long s(long n) { long s = 0; for (long i = 0; i < n; i++) { s += i; } return s; } public static void main(String[] args) { long start = System.nanoTime(); System.out.println(s(1000000000)); long end = System.nanoTime(); System.out.println((end - start)/1000000); } }
C ++编译器:gcc 4.4.0和Java:jdk 1.6.0
Java: 2795 ms
C++ : 0.013517 ms
它说C ++比Java快206777倍! 没门! 我的测试有什么问题?
显示您使用的编译器选项。 而你的真实代码( #include
不是你真正的代码)。
您的C ++编译器比Java编译器更加智能(在您的情况下这是正确的,但并非每个C ++编译器都比每个Java编译器更智能),并且它预先计算了结果。 你唯一要计时的是printf
调用。
在Java使用的大多数任务中,它的表现与C ++一样。
VM语言(Java,C#)具有与JIT编译相关的额外成本,但也受益于更高效的内存分配和跨共享库的内联。 而C ++在访问OS系统调用方面要快得多。 除此之外,可以仔细调整C ++内存布局以实现缓存行为; 你没有在托管语言中获得这种级别的控制。
哪些因素影响更大是完全针对特定应用的。 任何人都在做一句“C ++比Java更快”或“Java比C ++更快”的一揽子声明,这是一个白痴。 平均值无关紧要。 您的申请表现很重要。
这是我的certificate,gcc正在预先计算答案。
在这段代码上:
#include #include unsigned long long s(unsigned long long n) { unsigned long long s = 0; for (unsigned long long i = 0; i < n; i++) s += i; return s; } int main( int argc, char** argv ) { LARGE_INTEGER freq, start, end; QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&start); printf("%llu\n", s(1000000000)); QueryPerformanceCounter(&end); double d = (double) (end.QuadPart - start.QuadPart) / freq.QuadPart * 1000.0; printf("Delta: %f\n", d); QueryPerformanceCounter(&start); printf("%llu\n", s(atol(argv[1]))); QueryPerformanceCounter(&end); d = (double) (end.QuadPart - start.QuadPart) / freq.QuadPart * 1000.0; printf("Delta: %f\n", d); return 0; }
使用gcc-4.3.4,使用命令行./g++-4 -omasoud-gcc.exe -O3 masoud.cpp
:
bash-3.2# ./masoud-gcc 1000000000 499999999500000000 Delta: 0.845755 499999999500000000 Delta: 1114.105866
相比之下,MSVC ++ 16.00.40219.01 for x64(2010 SP1),命令行cl /Ox masoud.cpp
:
> masoud 1000000000 499999999500000000 Delta: 229.684364 499999999500000000 Delta: 354.275606
VC ++没有预先计算答案,但64位代码确实执行循环的速度提高了三倍以上。 这是Java应该接近的速度。
更有趣的事实:gcc比它生成的代码更快地预先计算答案以计算出答案。 编译gcc的时间:
real 0m0.886s user 0m0.248s sys 0m0.185s
我想gcc将你s
方法编译成:
unsigned long long s(unsigned long long n) { return n*(n+1)/2; }
…虽然java JIT没有。
我不是专家,但gcc优化过程可能包含比JIT在合理时间内可以做的更多的传递。 这也是为什么gcc编译可能需要很长时间才能使java程序立即启动(尽管JIT必须在程序运行之前编译,链接和优化所有内容)。
java编译器(javac)很少进行优化,比如常量折叠,但这几乎都是。 每个主要的优化(内联等)都是由JIT完成的,所以如果它不希望用户在启动之前等待太久,它必须快点。 另一方面,由于gcc静态编译和优化所有内容,因此只需要它就可以使用。
编辑:
应该很容易知道优化是否存在差异:使用s(1000)然后使用s(100000000000000)运行两个程序。 如果我是真的,那么c ++程序对于两个调用可能需要完全相同的时间,而在第二种情况下需要更长时间才能完成。
首先,您可能不希望各自的打印function成为您的基准测试的一部分,除非您真正关心它们的速度有多快。
关于Java或C ++是否更快,没有一个直接的答案……这取决于。 当编译器可以进行一些不可用于C ++的优化时,Java可以更快。 所以这取决于你具体做什么以及编译器选项是什么。