【问题标题】:C++ Performance: template vs boost.anyC++ 性能:模板与 boost.any
【发布时间】:2012-12-15 00:34:33
【问题描述】:

我想知道在任何可以使用模板的地方使用 boost.any(没有 RTTI)类是否会减慢程序的速度。由于 boost any 实际上是一个模板类的包装器,因此可以说使用现代编译器优化它会产生相同的效果,对吗?

tpl_vs_any.hpp

#include <iostream>
#include <vector>

using namespace std;

template<class T> class tpl
{
    T content;
public:
    tpl(const T& value) : content(value) {}
    operator T() const
    {
        return content;
    }
};

class any
{
public:

    any() : content(0) {}

    any(const any& other) : content(other.content -> clone()) {}

    template<class T> any(const T& value) : content(new holder<T>(value))
    {
    }

    ~any() 
    {
        delete content;
    }

    class placeholder
    {
    public:
        placeholder() {}
        virtual placeholder* clone() const = 0;
    };

    template<class T> class holder : public placeholder
    {
    public:
        T content;

        holder(const T& value) : content(value) {}
        ~holder() {}

        placeholder* clone() const
        {
            return new holder<T>(content);
        }
    };

    template<class T> operator T () const
    {
        return dynamic_cast<holder<T>*>(content)->content;
    }

    placeholder* content;
};

template<class T> void test()
{
    for (int i = 0; i < 10000; ++i)
    {
        vector<T> a;
        a.push_back(23.23);
        a.push_back(3.14);

        double x = (double)a[0];
    }
}

那么这样说对吗:

test<any>();

和以下一样快:

test<tpl<double>>();

假设您知道,就像编译器在第二个示例中所做的那样,boost::any 在这种情况下仅用作双精度? (任何类都没有 RTTI)。

我更想知道支持和反对这篇论文的论点。

另外,这些方法之间是否存在差异的具体情况?

编辑: 性能测试 2:

  • 示例 1:1,966.57 毫秒
  • 示例 2:1,320.37 毫秒

好像有比较大的区别。

编辑 2: 由于将主要数据类型 double 与类 any 进行比较是不公平的,因此我进行了新测试:

#include "tpl_vs_any.hpp"

int main()
{
    test<any>();
    return 0;
}

速度:1,794.54 毫秒

#include "tpl_vs_any.hpp"

int main()
{
    test<tpl<double>>();
    return 0;
}

速度:1,715.57 毫秒

多次测试,几乎相同的基准。

【问题讨论】:

  • boost.any 执行类型擦除、RTTI 和虚函数调度。它根本无法与直接静态编译的模板相提并论。
  • std::cout nullptr.me/2011/07/07/dissecting-any
  • 基准测试的时间可能主要是写入标准输出。
  • 另外你为什么提到boost::any然后不在你的任何一个基准测试中使用它?
  • @David Brown class any 是没有 RTTI 的 boost::any 的最小化版本。我会做一个新的测试。

标签: c++ templates boost boost-any


【解决方案1】:

那么这样说对吗:

...

和以下一样快:

...

假设您知道,就像编译器在第二个示例中所做的那样, boost::any 在这种情况下仅用作双精度数?

没有。当前的编译器远远没有达到那种自省水平。 boost::any 会更慢。

当然,您可以只运行代码并自己找出答案。

【讨论】:

    【解决方案2】:

    boost::any 内部包含一个指向对象的指针,它使用new 分配该对象。使std::vector 明显比std::list 快的原因之一是vector 将其所有对象保存在单个分配中的连续存储中,除了显着减少内存分配开销之外,这也是很多对缓存更友好。

    还有在分配中添加 RTTI 的细节,这通常是微不足道的开销,但在像 double 这样非常小的类型的情况下会显着增加存储开销。

    boost::any 不是标准的一部分;它是特定模板的特定实现。因此,您不妨对其进行基准测试;没有一堆其他竞争的“标准实现”。

    【讨论】:

    • 我不太清楚 RTTI 无关紧要。 “假设您知道,就像编译器在第二个示例中所做的那样, boost::any 在这种情况下仅用作双精度”
    • @Tim,这并没有绕过分配,imo 比 RTTI 重要得多。但是,我认为您高估了编译器理解 std::vector 和 boost::any 内部情况的能力。
    • 差异很小,请参阅我最新的性能分析。关于分配;我想班级越大,差异越小?
    • @Tim,存储位置(缓存)效应在大型向量上最为明显。可能大物体也会减少这里的差异;我通常更喜欢避免大对象的向量。 (出队是一个不错的折衷方案。)在 Stroustrup 的 2012 Going Native 主题演讲中,有一些很棒的幻灯片,第 43-48 页:ecn.channel9.msdn.com/events/GoingNative12/GN12Cpp11Style.pdf 我认为主题演讲本身仍然可以查看。我希望 vector<:any> 的行为更像列表,而不是 Stroustrup 基准中的向量。
    • 非常有趣和清晰的文章!感谢您的反馈。
    猜你喜欢
    • 2010-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-19
    • 1970-01-01
    • 2011-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多