【问题标题】:Traits vs virtual overhead特征与虚拟开销
【发布时间】:2017-07-30 16:11:28
【问题描述】:

我看过一个关于特质的 Alexandrescu 教程,我有一些想法要分享。这是代码:

// Example 6: Reference counting traits
//
template <class T>
class RefCountingTraits
{
    static void Refer(T* p)
    {
    p->IncRef(); // assume RefCounted interface
    }

    static void Unrefer(T* p)
    {
    p->DecRef(); // assume RefCounted interface
    }
};

template <>
class RefCountingTraits<Widget>
{
    static void Refer(Widget* p)
    {
    p->AddReference(); // use Widget interface
    }
    static void Unrefer(Widget* p)
    {
    // use Widget interface
    if (p->RemoveReference() == 0)
        delete p;
    }
};

在这种情况下,与标准虚函数成员情况相比,我们有多少开销?在这种情况下,我们也没有直接访问对象:我们仍在传递一个指针。编译器是否能够以同样的方式对其进行优化?

【问题讨论】:

    标签: c++ performance templates virtual traits


    【解决方案1】:

    在典型的生产优化级别(-O2/O2),您可以期望显示的所有代码都被内联,并且没有副作用的位被优化掉。这样就剩下对IncRefAddReference 的实际调用以及对delete-ion 的检查。

    如果使用了virtual 函数,并且如果引用计数代码很简单(例如不是线程安全的),由于调度表查找和离线函数,它可能会慢一个数量级调用,但这会因编译器、确切的优化设置、CPU、调用约定等而有所不同。

    与往常一样,当您必须关心、分析和实验时。

    【讨论】:

    • 如果我理解得很好,优化后的代码就像直接调用p->IncRef()一样,没有指针复制权?似乎多了一个数量级。完全同意分析:)
    • "...对吗?" 对。 “太多一个数量级” - 即使将调用由运行时开关选择的琐碎函数与虚拟调度进行对比,在this benchmark 中也给出了 9.2 倍的系数,但总是可以衡量和分享您自己的基准代码/发现。在这种情况下,IncRef()DecRef() 在需要线程安全的情况下可能不是那么微不足道,因此额外虚拟调度的影响将是一个较小的因素。
    猜你喜欢
    • 2018-06-20
    • 1970-01-01
    • 2020-02-02
    • 1970-01-01
    • 2019-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多