基准C ++与Java,不切实际的结果

时间:2011-09-27 14:05:05

标签: java c++ gcc benchmarking

我做了一个简单的测试,我知道C ++更快但我的测试结果不切实际。

C ++代码是:

#include <stdio.h>
#include <windows.h>

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倍!没门!我的测试有什么问题?

3 个答案:

答案 0 :(得分:6)

显示您使用的编译器选项。你的真实代码(#include <stdio>不是真正的代码)。

您的C ++编译器比Java编译器更加智能(平均而言,这是正确的,但并非每个C ++编译器都比每个Java编译器更智能),并且它预先计算了结果。你唯一要计时的是printf电话。

在Java使用的大多数任务中,它的表现与C ++一样。

VM语言(Java,C#)具有与JIT编译相关的额外成本,但也可以从更高效的内存分配和跨共享库的内联中获益。而C ++在访问OS系统调用方面要快得多。除此之外,可以仔细调整C ++内存布局以实现缓存行为;你没有在托管语言中获得这种控制水平。

这些因素中哪一个影响更大,完全取决于应用程序。任何做出“C ++比Java更快”或“Java总体上比C ++更快”的一揽子声明的人都是白痴。平均值无关紧要。您的申请表现很重要。


这是我的证明,gcc正在预先计算答案。

关于此代码:

#include <stdio.h>
#include <windows.h>

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

答案 1 :(得分:2)

我猜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 ++程序对于两个调用可能需要完全相同的时间,而在第二种情况下需要更长时间才能完成java。

答案 2 :(得分:-1)

首先,您可能不希望相应的打印功能成为您的基准测试的一部分,除非您真的关心它们的速度有多快。

关于Java或C ++是否更快,没有一个直接的答案......这取决于。当编译器可以进行一些不可用于C ++的优化时,Java可以更快。所以它取决于你具体做什么以及编译器选项是什么。