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

发布于 2024-12-07 02:15:05 字数 1315 浏览 1 评论 0原文

我做了一个简单的测试,我知道 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 毫秒

C++:0.013517 毫秒

它说 C++ 比 Java 快 206777 倍!决不!我的测试出了什么问题?

I did a simple test, I know C++ is faster but the results of my test is unrealistic.

C++ code is:

#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 code is:

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++ compiler: gcc 4.4.0 and Java: jdk 1.6.0

Java: 2795 ms

C++ : 0.013517 ms

It says C++ is 206777 times faster than Java! No way! What is wrong in my test?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

看轻我的陪伴 2024-12-14 02:15:05

显示您使用的编译器选项。而您的真实代码(#include 不是您的真实代码)。

您的 C++ 编译器比 Java 编译器聪明得多(平均而言,在您的情况下确实如此,但并非每个 C++ 编译器都比每个 Java 编译器更聪明),并且它预先计算了结果。您唯一需要计时的是 printf 调用。

在大多数使用 Java 的任务中,它的性能与 C++ 差不多。

VM 语言(Java、C#)具有与 JIT 编译相关的额外成本,但也受益于更高效的内存分配和跨共享库的内联。 C++ 访问操作系统系统调用的速度要快得多。除此之外,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

Show the compiler options you used. And your REAL code (#include <stdio> isn't your real code).

Your C++ compiler is much smarter than your Java compiler (this is true on average and in your case, but not every C++ compiler is smarter than every Java compiler), and it precomputed the result. The only thing you're timing is the printf call.

On most of the tasks Java is used for, it performs about as well as C++.

VM languages (Java, C#) have additional costs related to JIT compilation, but also benefit from more efficient memory allocation and inlining across shared libraries. And C++ is much much faster at accessing OS syscalls. Beyond that, C++ memory layouts can be carefully tuned for cache behavior; you don't get that level of control in managed languages.

Which of these factors has more influence is completely application-specific. Anyone making a blanket statement that "C++ is faster in general than Java" or "Java is faster in general than C++" is an idiot. Averages don't matter. Performance on YOUR application matters.


And here is my proof, that gcc is precomputing the answer.

On this code:

#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;
}

With gcc-4.3.4, using the command-line ./g++-4 -omasoud-gcc.exe -O3 masoud.cpp:

bash-3.2# ./masoud-gcc 1000000000
499999999500000000
Delta: 0.845755
499999999500000000
Delta: 1114.105866

By comparison, MSVC++ 16.00.40219.01 for x64 (2010 SP1), command-line cl /Ox masoud.cpp:

> masoud 1000000000
499999999500000000
Delta: 229.684364
499999999500000000
Delta: 354.275606

VC++ isn't precomputing the answer, but 64-bit code does execute the loop more than three times faster. This is the speed that Java ought to approach.


More fun facts: gcc precomputes the answer faster than the code it generates to calculate it out. Compile time for gcc:

real    0m0.886s
user    0m0.248s
sys     0m0.185s
递刀给你 2024-12-14 02:15:05

我猜 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 程序在第二种情况下需要更长的时间才能完成。

I guess that gcc compiled your s method into:

unsigned long long s(unsigned long long n)
{    
    return n*(n+1)/2;
}

...while the java JIT did not.

I'm no expert but gcc optimization process may contain more passes than what the JIT can do in a reasonable time. That's also why a gcc compilation may take ages while a java program launches itself immediatly (altough the JIT has to compile, link and optimize everything before the program can be run).

The java compiler (javac) does very few optimization, like constant folding, but that's pretty much all. Every major optimization (inlining, etc) is done by the JIT, so if it does not want the user to wait too long before launch, it must hurry. On the other hand, since gcc compiles and optimize everything statically, it can take as long as it needs.

EDIT:

It should be simple to know if there is a difference in optimizations: run your two programs with s(1000) and then with s(100000000000000). If I'm true, the c++ program may take the exact same time for both calls, while the java one while take longer to complete in the second case.

甜宝宝 2024-12-14 02:15:05

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

关于 Java 或 C++ 哪个更快,没有直接的答案……这取决于情况。当编译器可以进行一些 C++ 无法实现的优化时,Java 会更快。因此,这取决于您具体在做什么以及编译器选项是什么。

First of all, you probably don't want the respective print functions to be part of your benchmark unless you really care how fast those are.

There's not a straight answer as to whether Java or C++ is faster...it depends. Java can be faster when the compiler can do some optimizations that would not be available for C++. So it depends on what specifically you are doing and what the compiler options are.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文