Joh*_*Doe 18 c c++ performance c-libraries
我看到了这个链接,但我不是要求使用"extern"的代码性能下降.我的意思是没有"extern",在C++中使用C库时是否存在"上下文切换"? 在C++应用程序中使用纯C(非类包装)函数时是否有任何问题?
Bas*_*tch 36
C和C++都是编程语言规范(用英语编写,参见例如n1570,用于C11的规范)并且不谈论性能(但是关于程序的行为,即关于语义).
但是,您可能会使用诸如GCC或Clang之类的编译器,这些编译器不会带来任何性能损失,因为它为C和C++语言构建了相同类型的中间内部表示(例如GCC的GIMPLE和Clang的LLVM). ,因为C和C++代码使用兼容的ABI和调用约定.
实际上extern "C",不要更改任何调用约定,但禁用名称修改.但是,它对编译器的确切影响是特定于该编译器的.它可能(或不)禁用内联(但考虑-fltoGCC中的链接时优化).
某些C编译器(例如tinycc)会生成性能较差的代码.即使GCC或铛,当用于-O0或不明确使优化(例如,通过传球 -O1或者-O2等等)可能会产生缓慢的代码(和优化默认情况下它被禁用).
BTW,C++被设计为可与C互操作(并且强约束解释了C++的大多数缺陷).
在某些情况下,真正的C++代码可能比相应的正版C代码略快.例如,要对数字数组进行排序,您将在正版C++中使用std :: array和std :: sort,并且排序中的比较操作可能会被内联.使用C代码,您只需使用qsort,每次比较都会通过间接函数调用(因为编译器不是内联的qsort,即使理论上它可以......).
在其他一些情况下,真正的C++代码可能会稍微慢一点; 例如,几个(但不是全部)实现::operator new只是简单地调用malloc(然后检查失败),但没有内联.
实际上,从C++代码调用C代码或从C代码调用C++代码没有任何代价,因为调用约定是兼容的.
C longjmp工具可能比抛出C++异常更快,但它们没有相同的语义(请参阅堆栈展开),longjmp并且不能很好地融合C++代码.
如果你非常关心性能,那么在你的代码和基准测试中写两次(在真正的C和真正的C++中).您可能会观察到C和C++之间的微小变化(最多几个百分点),所以我根本不会打扰(而且您的性能问题实际上是不合理的).
上下文切换是与操作系统和多任务相关的概念,发生在运行抢占期间可执行的机器代码的进程上.如何获取该可执行文件(来自C编译器,来自C++编译器,来自Go编译器,来自SBCL编译器,或者是其他语言(如Perl或字节码Python)的解释器)是完全无关紧要的(因为上下文切换可能发生)在任何机器指令,在中断期间).阅读一些书籍,如操作系统:三个Eeasy Pieces.
Bee*_*ope 13
在基本级别,不,当从C++代码调用C库时,您将看不到任何类型的"切换"性能损失.例如,从C++调用另一个转换单元中定义的C方法应该具有与在另一个转换单元中调用C++(以相同的C类方式)实现的相同方法大致相同的性能.
这是因为C和C++编译器的常见的实现最终编译源下降到本机代码,并调用一个extern "C"函数,使用相同类型的有效负载call可能会出现一个C++调用.调用约定通常基于平台ABI,并且在任何一种情况下都类似.
除了基本事实之外,在调用C函数时可能仍然存在一些性能缺点,而不是在C++中实现相同的函数:
extern "C"并且从C++代码声明和调用的函数通常不会被内联(因为根据定义它们没有在头文件中实现),这会抑制整个主机可能非常强大的优化0.std::string在你的C++代码,你需要选择一个不同的类型将其传递到C代码- char *是常见的,但失去有关显式长度的信息,可能比C++解决方案慢.许多类型没有直接的C等价物,因此您可能会遇到代价高昂的转换.malloc和free用于动态内存管理,而C++代码通常使用new和delete(并且通常更喜欢尽可能地隐藏其他类后面的调用).如果您需要使用一种将在其他语言中释放的语言分配内存,则可能会导致不匹配,您需要回拨"其他"语言来执行免费,或者可能不必要的副本等.上述问题仅适用于纯C++实现与C语言的对比,并不意味着在调用C时性能会下降:它实际上是在回答"为什么可以在C和C的混合中编写应用程序"的问题. C++比纯C++慢?" 此外,上述问题主要是对非常短的呼叫的关注,其中上述开销可能很大.如果你在C中调用一个冗长的函数,那就不是问题了."数据类型不匹配"可能仍然会让你感到厌烦,但这可以在C++方面进行设计.
0有趣的是,链接时优化实际上允许在C++代码中内联 C方法,这是LTO的一个小问题.当然,这通常取决于使用适当的LTO选项从源代码构建C库.
1例如,除标准布局类型之外的其他任何东西.
2至少部分地减轻了这一事实,即许多C++标准库调用最终委托C库例程进行"大量"提升,例如如何std::copy调用memcpy或memset何时可能以及大多数new实现最终调用的方式malloc.
| 归档时间: |
|
| 查看次数: |
1834 次 |
| 最近记录: |