【问题标题】:How fast is dynamic_cast<>dynamic_cast<> 有多快
【发布时间】:2023-03-26 13:44:01
【问题描述】:

... 与典型的 std::string::operator==() 大致相比?我在下面提供了更多详细信息,我不确定它们是否相关。具有复杂性或近似性的答案就足够了。谢谢!

详细信息:我将在 for 循环中使用它来遍历列表以查找一些特定实例。我估计我的平均继承水平为 3.5 个类。我正在寻找的那个有一个父类,一个祖父类,并且在这两个“接口”之上,即带有一对virtual void abc() = 0; 的抽象类。

我要寻找的那个没有子类。

【问题讨论】:

  • -1 如前所述,想要在dynamic_caststd::string::operator== 之间进行比较,这个问题毫无意义。如果消除了这种愚蠢,那么答案就是“多快?”只是一个单词“measure”。
  • @Alf,如果 OP 面临的选项是执行 dynamic_cast 或比较 type stringtypeid.name 或用户编写的虚函数)这个问题可能有意义。
  • @Alf:这个问题对我来说很有意义。 Crashworks 的测量结果表明存在显着差异,我认为这是非常普遍的。这节省了我的时间(编码而不是测量)。在抱怨和高效之间,你选择了愚蠢的选择。

标签: c++ performance stdstring dynamic-cast


【解决方案1】:

这在很大程度上取决于您的编译器、特定的类层次结构、硬件以及各种因素。您确实需要直接在您的特定应用程序中对其进行测量。为此,您可以使用rdtsc 或(在Windows 上)QueryPerformanceCounter 来获得相对高精度的计时器。一定要对几千个 dynamic_casts 的循环或 sled 进行计时,因为即使 QPC 也只有 ¼μs 的分辨率。

在我们的应用程序中,dynamic_cast 大约需要 1 微秒,字符串比较大约需要 3ns/字符。

dynamic_cast 和 stricmp() 都位于我们配置文件的顶部,这意味着使用它们的性能成本很高。 (坦率地说,在我们的工作中,将这些功能放在如此高的位置是不可接受的,我不得不去重写一堆使用它们的其他人的代码。)

【讨论】:

  • 哇。 dynamic_cast 比字符比较慢三个数量级?这很奇怪。 编辑虽然不是那么奇怪,因为dynamic_cast 可能需要遍历内存中的一棵树(这意味着随机访问和多个缓存未命中),而字符串比较在缓存内存上工作。
  • @KonradRudolph 我想我可以重新运行时间并将它们发布在我的博客上。我最后一次运行它们是几年前。此外,我们的班级层次结构是巨大的。 dynamic_cast 的成本随着子代和祖先之间的继承数量而增加。
  • @JonasByström 谢谢,但我的建议是你真的应该自己测量——我发现 dynamic_cast 的时间变化很大取决于大小类树,无论你使用 MSVC 还是 GCC,等等。对于您的应用,情况可能会有所不同,设置和运行一个简单的计时测试应该只需要半个小时。
  • @Crashworks 可能会花费我更长的时间,因为我要移植到四个平台 - 所以谢谢,但不谢谢。即使我的 dynamic_cast 比你的快 50 倍(我认为这不太可能),它仍然比 str== 慢。我认为这是一个非常自然的结论,即 C++ 内置在任何一个平台上几乎都不会快 200 倍或更多,更不用说在所有四个平台上。
  • @JonasByström 差异可能大得惊人。 1us/3ns 比率适用于我怀疑您正在查看的 PowerPC 平台之一上的 MSVC。另一个 PPC 平台上的 GCC 接近 500ns/3ns。在 x86 MSVC 上,dynamic_cast 在小类层次结构和频繁命中的情况下与四个 strcmp 相当(但对于深层层次结构的未命中情况更糟)。在另一个 x86 平台的 GCC 上,strcmp() 的表现比 dynamic_cast 差,因为 GCC 的字符串比较实现太差了。这个特殊的东西对有序/无序的硬件差异呈指数级敏感。
【解决方案2】:

最好的答案是测量,我猜dynamic_cast 比比较除最短字符串以外的任何字符串(甚至可能比短字符串)都要快。

话虽这么说,试图确定对象的类型通常是设计不佳的标志,根据Liskov's substitution principle,您应该只对待对象相同,并让虚函数以正确的方式运行,而无需检查类型外。


编辑:重新阅读您的问题后,我会坚持我要寻找的那个没有子类。 在这种情况下,您可以直接使用typeid,我相信它应该比您的任何一个选项都快(尽管在我看来寻找特定类型仍然是代码味道

#include <iostream>
#include <typeinfo>

struct top {
    virtual ~top() {} 
};

struct left : top { };
struct right : top { };

int main()
{
    left lft;
    top &tp = lft;   
    std::cout << std::boolalpha << (typeid(lft) == typeid(left)) << std::endl; 
    std::cout << std::boolalpha << (typeid(tp) == typeid(left)) << std::endl; 
    std::cout << std::boolalpha << (typeid(tp) == typeid(right)) << std::endl; 
}

输出:

是的
真的
假的

【讨论】:

  • 我要求不必测量,代码是可移植的,我也不需要准确性。我猜@Crashworks 测量值大致是通用的。您的第二段没有为这个问题增加任何价值。
  • 阅读 Crashwork 的答案和后续的cmets 了吗?他说:“我发现 dynamic_cast 的时间变化很大,这取决于类树的大小、您使用的是 MSVC 还是 GCC 等等。”换句话说,任何东西都不是通用的。
  • @JonasByström 我添加了另一个解决方案,它可能比您的两个选项都更快。
猜你喜欢
  • 1970-01-01
  • 2015-06-27
  • 1970-01-01
  • 1970-01-01
  • 2021-07-26
  • 1970-01-01
  • 2019-02-09
  • 1970-01-01
  • 2013-05-04
相关资源
最近更新 更多