简体   繁体   English

为什么 C++ 什么都不做时比 C 慢

[英]Why is C++ slower than C when doing literaly nothing

C++ is almost 4 times slower than C at doing nothing (at least on my machine). C++ 几乎比 C 慢 4 倍(至少在我的机器上)。 When the following file is compiled by g++, it is 4 times slower than with gcc:以下文件由 g++ 编译时,比 gcc 慢 4 倍:

int main() {}

With time sh -c 'for i in $(seq 0 1000); do./a.out; done'随着time sh -c 'for i in $(seq 0 1000); do./a.out; done' time sh -c 'for i in $(seq 0 1000); do./a.out; done' time sh -c 'for i in $(seq 0 1000); do./a.out; done' , I get 0.515s for the C version, and 2s for the C++ one. time sh -c 'for i in $(seq 0 1000); do./a.out; done' ,我得到 C 版本的 0.515s,C++ 版本的 2s。 Why is that?这是为什么?

There isn't a single thing done in this program, and the disassembled program is basically the same in both versions, so why is the C++ version roughly 4 times slower?这个程序什么都没做,两个版本的反汇编程序基本相同,为什么C++版本慢了大约4倍?

My guess is that the C++ library takes a longer time to load, but the assembly is so similar that I can't think of a reason for C++ to be so much slower.我的猜测是 C++ 库需要更长的时间来加载,但程序集非常相似,我想不出 C++ 这么慢的原因。

Edit: Well, it appears that I only partially disassembled the program ( objdump -d instead of objdump -D ), resulting in me not seeing the library being loaded.编辑:好吧,看来我只是部分反汇编了程序( objdump -d而不是objdump -D ),导致我看不到正在加载的库。 It is pretty obvious now seeing the disassembled output that the C++ version just takes longer to load its libraries.现在看到反汇编的 output 很明显,C++ 版本加载其库需要更长的时间。 What I first meant by "slightly differing" was that the addresses used in mov or call diverged without calling other functions (if I understand correctly the meaning of objdump 's output).我首先所说的“略有不同”的意思是movcall中使用的地址在没有调用其他函数的情况下发生了分歧(如果我正确理解objdump输出的含义)。

So the main question is solved, but 2 seconds is huge for a program that does nothing.所以主要问题解决了,但是 2 秒对于一个什么都不做的程序来说是巨大的。 I'm on a x86_64 processor if that helps, and I built the executable gcc empty.c and g++ empty.cpp .如果有帮助,我在 x86_64 处理器上,我构建了可执行文件gcc empty.cg++ empty.cpp I think the issue really is me using a HDD, thus taking more time to load libstd++ .我认为问题确实出在我使用硬盘驱动器上,因此需要更多时间来加载libstd++ I also built with the -static flag, and am now getting very similar results (0.246s and 0.241s).我还使用-static标志构建,现在得到非常相似的结果(0.246s 和 0.241s)。 The C binary is also exactly the same as the C++ one (if that's not a diff bug). C 二进制文件也与 C++ 二进制文件完全相同(如果这不是diff错误)。

C++ standard library initial startup is heavier than the C runtime. C++ 标准库初始启动重于 C 运行时。

C++ ABI needs to initialize some structures for basic language features. C++ ABI需要为基本语言特性初始化一些结构。 Mutex locks for thread-safe initialization of data , exeptions , thread local storage , RTTI , etc.用于线程安全初始化数据异常线程本地存储RTTI等的互斥锁。

This is why an empty executable created with a C++ compiler will start slower than an empty C program.这就是为什么用 C++ 编译器创建的空可执行文件比空的 C 程序启动得慢。 Likewise, an empty program created with Assembly language will start much faster then a similar program created with C with a full-featured C runtime (CRT, GNU LIBC, etc).同样,使用汇编语言创建的空程序的启动速度要比使用 C 创建的具有全功能 C 运行时(CRT、GNU LIBC 等)的类似程序快得多。

In fact, you compare nothing at all, because your program does nothing at all.事实上,您根本不比较任何东西,因为您的程序根本不做任何事情。 What you got is not the program execution time , which in your case is null, but the process execution time , ie load+run+terminate, which is longer if your program needs more resources.你得到的不是程序执行时间,在你的情况下是null,而是进程执行时间,即加载+运行+终止,如果你的程序需要更多资源,它会更长。

Some numbers could lead some light on this:一些数字可以对此有所启发:

say we have emptyc and emptycpp , respectively compiled with gcc-10.3 and g++-10.3假设我们有emptycemptycpp ,分别用 gcc-10.3 和 g++-10.3 编译

On my system:在我的系统上:

  • emptyc : emptyc

    • file size: 13232文件大小:13232
    • elf dynamic section: 17 entries (1 shared lib)精灵动态部分:17 个条目(1 个共享库)
    • truss syscall report: 48 syscalls including 6 open and 11 mmap truss 系统调用报告:48 个系统调用,包括 6 个打开和 11 个 mmap
  • emptycpp

    • file size: 13312文件大小:13312
    • elf dynamic section: 20 entries (4 shared libs)精灵动态部分:20 个条目(4 个共享库)
    • truss syscall report: 88 syscalls including 15 open and 29 mmap truss 系统调用报告:88 个系统调用,包括 15 个打开和 29 个 mmap

Conclusion :结论

A program compiled with g++ needs more resources than the same program compiled with gcc. A process generating 88 syscalls is probably slower than a process generating 48.使用 g++ 编译的程序比使用 gcc 编译的同一程序需要更多资源。生成 88 个系统调用的进程可能比生成 48 个系统调用的进程慢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM