【问题标题】:C++ Low latency Design: Function Dispatch v/s CRTP for Factory implementationC++ 低延迟设计:Function Dispatch v/s CRTP for Factory 实现
【发布时间】:2015-03-14 18:07:36
【问题描述】:

作为系统设计的一部分,我们需要实现工厂模式。结合工厂模式,我们还使用 CRTP 来提供一组基本功能,然后可以通过派生类对其进行自定义。

下面的示例代码:

class FactoryInterface{
    public:
     virtual void doX() = 0;
};

//force all derived classes to implement custom_X_impl 
template< typename Derived, typename Base = FactoryInterface>
class CRTP : public Base 
{
    public:
    void doX(){
        // do common processing..... then
        static_cast<Derived*>(this)->custom_X_impl();
    }
};

class Derived: public CRTP<Derived>
{
    public:
        void custom_X_impl(){
        //do custom stuff
        }
};

虽然这种设计很复杂,但它确实提供了一些好处。初始虚函数调用之后的所有调用都可以内联。派生类 custom_X_impl 调用也很高效。

我编写了一个比较程序来比较使用函数指针和虚函数的类似实现(紧密循环、重复调用)的行为。这种设计在使用 O2 和 O3 的 gcc/4.8 中取得了胜利。

然而,一位 C++ 大师昨天告诉我,考虑到缓存未命中,大型执行程序中的任何虚函数调用都可能花费可变时间,我可以使用 C 风格的函数表查找和 gcc 热列表实现潜在的更好性能职能。但是,在上面提到的示例程序中,我仍然看到 2 倍的成本。

我的问题如下: 1. 上师的说法是真的吗?对于任何一个答案,有没有我可以参考的链接。 2. 有没有我可以参考的低延迟实现,有一个基类在派生类中调用自定义函数,使用函数指针? 3. 有什么改进设计的建议吗?

欢迎任何其他反馈。

【问题讨论】:

    标签: c++ gcc class-design crtp low-latency


    【解决方案1】:

    你的大师指的是 gcc 编译器的 hot 属性。这个attribute的效果是:

    该功能被更积极地优化并且在许多目标上它是 放置在文本部分的特殊小节中,因此都很热 函数看起来很接近,提高了局部性。

    所以是的,在一个非常大的代码库中,热列表函数可能会保留在缓存中,准备好立即执行,因为它会避免缓存未命中。

    你可以完美地将这个属性用于成员函数:

    struct X {
        void test()  __attribute__ ((hot)) {cout <<"hello, world !\n"; }
    };
    

    但是...

    当您使用虚函数时,编译器通常会生成一个vtable,该vtable 在类的所有对象之间共享。该表是指向函数的指针表。事实上——你的大师是对的——没有什么能保证这张表保留在缓存中。

    但是,如果你手动创建一个“C 风格”的函数指针表,问题是完全一样的。虽然函数可能保留在缓存中,但没有什么可以确保您的函数表也保留在缓存中。

    这两种方法的主要区别在于:

    • 在虚函数的情况下,编译器知道虚函数是一个热点,并且可以决定确保将 vtable 也保留在缓存中(我不知道 gcc 是否可以这样做或者如果有计划这样做)。

    • 在手动函数指针表的情况下,您的编译器不会轻易推断该表属于热点。因此,这种手动优化的尝试很可能适得其反。

    我的意见:永远不要试图优化自己,编译器可以做得更好。

    结论

    相信您的基准。并相信您的操作系统:如果您的函数或数据经常被访问,现代操作系统很有可能会在其虚拟内存管理以及编译器生成的任何内容中考虑到这一点。

    【讨论】:

    • 谢谢克里斯托夫。您的分析也与我在性能测试中看到的有关。您是否看到设计中有任何潜在的优化?
    • 我认为进一步优化会很困难!由于 doX() 必须是虚拟的,并且 Derived 是客户定义的,因此我找不到其他具有较少间接性的替代方案。
    猜你喜欢
    • 2010-11-26
    • 2021-08-28
    • 2021-10-30
    • 1970-01-01
    • 2021-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-31
    相关资源
    最近更新 更多