RTTI有多贵?
我知道使用 RTTI 会影响资源,但影响有多大?我看过的所有地方都只是说RTTI 很贵",但实际上没有一个提供任何基准或定量数据来保护内存、处理器时间或速度.
I understand that there is a resource hit from using RTTI, but how big is it? Everywhere I've looked just says that "RTTI is expensive," but none of them actually give any benchmarks or quantitative data reguarding memory, processor time, or speed.
那么,RTTI 有多贵?我可能会在只有 4MB 内存的嵌入式系统上使用它,所以每一位都很重要.
So, just how expensive is RTTI? I might use it on an embedded system where I have only 4MB of RAM, so every bit counts.
根据 S. Lott 的回答,这样会更好如果我包括我实际在做的事情.我正在使用一个类来传递不同长度的数据并且可以执行不同的操作,因此使用只有虚函数.似乎使用几个 dynamic_cast
可以解决这个问题,允许不同的派生类通过不同的级别,但仍然允许它们以完全不同的方式运行.
As per S. Lott's answer, it would be better if I include what I'm actually doing. I am using a class to pass in data of different lengths and that can perform different actions, so it would be difficult to do this using only virtual functions. It seems that using a few dynamic_cast
s could remedy this problem by allowing the different derived classes to be passed through the different levels yet still allow them to act completely differently.
根据我的理解,dynamic_cast
使用 RTTI,所以我想知道在有限的系统上使用它有多可行.
From my understanding, dynamic_cast
uses RTTI, so I was wondering how feasable it would be to use on a limited system.
推荐答案
不管编译器如何,只要你负担得起,你总是可以节省运行时间
Regardless of compiler, you can always save on runtime if you can afford to do
if (typeid(a) == typeid(b)) {
B* ba = static_cast<B*>(&a);
etc;
}
代替
B* ba = dynamic_cast<B*>(&a);
if (ba) {
etc;
}
前者只涉及std::type_info
的一个比较;后者必然涉及遍历继承树和比较.
The former involves only one comparison of std::type_info
; the latter necessarily involves traversing an inheritance tree plus comparisons.
过去……就像大家说的那样,资源使用是特定于实现的.
Past that ... like everyone says, the resource usage is implementation specific.
我同意其他人的意见,即提交者出于设计原因应避免使用 RTTI.然而,使用 RTTI 有很好的理由(主要是因为 boost::any).请记住,了解其在常见实现中的实际资源使用情况很有用.
I agree with everyone else's comments that the submitter should avoid RTTI for design reasons. However, there are good reasons to use RTTI (mainly because of boost::any). That in mind, it's useful to know its actual resource usage in common implementations.
我最近对 ??GCC 中的 RTTI 进行了大量研究.
I recently did a bunch of research into RTTI in GCC.
tl;dr: GCC 中的 RTTI 使用的空间可以忽略不计,并且 typeid(a) == typeid(b)
在许多平台上(Linux、BSD 和嵌入式平台,但不是 mingw32)非常快).如果您知道自己将永远在一个受祝福的平台上,那么 RTTI 非常接近免费.
tl;dr: RTTI in GCC uses negligible space and typeid(a) == typeid(b)
is very fast, on many platforms (Linux, BSD and maybe embedded platforms, but not mingw32). If you know you'll always be on a blessed platform, RTTI is very close to free.
重要细节:
GCC 更喜欢使用特定的供应商中立"C++ ABI[1],并且始终将此 ABI 用于 Linux 和 BSD 目标[2].对于支持此 ABI 和弱链接的平台,typeid()
为每种类型返回一致且唯一的对象,甚至跨越动态链接边界.您可以测试 &typeid(a) == &typeid(b)
,或者仅依赖于便携式测试 typeid(a) == typeid(b)
实际上只是在内部比较一个指针.
GCC prefers to use a particular "vendor-neutral" C++ ABI[1], and always uses this ABI for Linux and BSD targets[2]. For platforms that support this ABI and also weak linkage, typeid()
returns a consistent and unique object for each type, even across dynamic linking boundaries. You can test &typeid(a) == &typeid(b)
, or just rely on the fact that the portable test typeid(a) == typeid(b)
does actually just compare a pointer internally.
在 GCC 的首选 ABI 中,类 vtable 总是 持有一个指向每个类型的 RTTI 结构的指针,尽管它可能不被使用.因此,typeid()
调用自身应该只花费与任何其他 vtable 查找(与调用虚拟成员函数相同)的成本,并且 RTTI 支持 应该't 为每个对象使用任何额外的空间.
In GCC's preferred ABI, a class vtable always holds a pointer to a per-type RTTI structure, though it might not be used. So a typeid()
call itself should only cost as much as any other vtable lookup (the same as calling a virtual member function), and RTTI support shouldn't use any extra space for each object.
据我所知,GCC 使用的 RTTI 结构(这些都是 std::type_info
的子类)只为每种类型保存几个字节,除了名称.即使使用 -fno-rtti
,我也不清楚输出代码中是否存在名称.无论哪种方式,编译后的二进制文件大小的变化都应该反映运行时内存使用的变化.
From what I can make out, the RTTI structures used by GCC (these are all the subclasses of std::type_info
) only hold a few bytes for each type, aside from the name. It isn't clear to me whether the names are present in the output code even with -fno-rtti
. Either way, the change in size of the compiled binary should reflect the change in runtime memory usage.
一个快速实验(在 Ubuntu 10.04 64 位上使用 GCC 4.4.3)表明 -fno-rtti
实际上增加一个简单测试程序的二进制大小几百字节.这在 -g
和 -O3
的组合中一致发生.我不确定为什么尺寸会增加;一种可能性是 GCC 的 STL 代码在没有 RTTI 的情况下表现不同(因为异常不起作用).
A quick experiment (using GCC 4.4.3 on Ubuntu 10.04 64-bit) shows that -fno-rtti
actually increases the binary size of a simple test program by a few hundred bytes. This happens consistently across combinations of -g
and -O3
. I'm not sure why the size would increase; one possibility is that GCC's STL code behaves differently without RTTI (since exceptions won't work).
[1] 称为 Itanium C++ ABI,记录在 http://www.codesourcery.com/public/cxx-abi/abi.html.名称非常混乱:名称指的是原始开发架构,尽管 ABI 规范适用于许多架构,包括 i686/x86_64.GCC 内部源代码和 STL 代码中的注释将 Itanium 称为新"ABI,与他们之前使用的旧"ABI 形成对比.更糟糕的是,新"/安腾 ABI 指的是通过 -fabi-version
可用的所有版本;旧" ABI 早于此版本控制.GCC 在 3.0 版本中采用了 Itanium/versioned/"new" ABI;如果我正确阅读了他们的变更日志,则在 2.95 及更早版本中使用了旧"ABI.
[1] Known as the Itanium C++ ABI, documented at http://www.codesourcery.com/public/cxx-abi/abi.html. The names are horribly confusing: the name refers to the original development architecture, though the ABI specification works on lots of architectures including i686/x86_64. Comments in GCC's internal source and STL code refer to Itanium as the "new" ABI in contrast to the "old" one they used before. Worse, the "new"/Itanium ABI refers to all versions available through -fabi-version
; the "old" ABI predated this versioning. GCC adopted the Itanium/versioned/"new" ABI in version 3.0; the "old" ABI was used in 2.95 and earlier, if I am reading their changelogs correctly.
[2] 我找不到按平台列出std::type_info
对象稳定性的任何资源.对于我可以访问的编译器,我使用了以下内容:echo "#include
.从 GCC 3.0 开始,此宏在 GCC 的 STL 中控制 operator==
对于 std::type_info
的行为.我确实发现 mingw32-gcc 遵守 Windows C++ ABI,其中 std::type_info
对象对于跨 DLL 的类型不是唯一的;typeid(a) == typeid(b)
在幕后调用 strcmp
.我推测在像 AVR 这样没有代码链接的单程序嵌入式目标上,std::type_info
对象总是稳定的.
[2] I couldn't find any resource listing std::type_info
object stability by platform. For compilers I had access to, I used the following: echo "#include <typeinfo>" | gcc -E -dM -x c++ -c - | grep GXX_MERGED_TYPEINFO_NAMES
. This macro controls the behavior of operator==
for std::type_info
in GCC's STL, as of GCC 3.0. I did find that mingw32-gcc obeys the Windows C++ ABI, where std::type_info
objects aren't unique for a type across DLLs; typeid(a) == typeid(b)
calls strcmp
under the covers. I speculate that on single-program embedded targets like AVR, where there is no code to link against, std::type_info
objects are always stable.
相关文章