boost :: variant vs. polymorphism,与clang和gcc有很大不同的性能结果

我试图弄清楚boost :: variant的执行时间与多态方法有多大差异.在我的第一次测试中,我在
gcc 4.9.1和clang llvm 3.5上获得了非常不同的结果.

你可以在下面找到代码.这是我的结果:

clang llvm

polymorphism: 2.16401
boost::variant: 3.83487

GCC:

polymorphism: 2.46161
boost::variant: 1.33326

我用-O3编译了两个.
有人能解释一下吗?

#include <iostream>
#include <vector>
#include <algorithm>
#include <boost/variant.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <ctime>

struct value_type {

    value_type() {}
    virtual ~value_type() {}
    virtual void inc() = 0;
};

struct int_type : value_type {

    int_type() : value_type() {}
    virtual ~int_type() {}

    void inc() { value += 1; }

      private:
    int value = 0;
};

struct float_type : value_type {

    float_type() : value_type() {}
    virtual ~float_type() {}

    void inc() { value += 1; }

      private:
    float value = 0;
};

void dyn_test() {

    std::vector<std::unique_ptr<value_type>> v;
    for (int i = 0; i < 1024; i++) {
        if (i % 2 == 0)
            v.emplace_back(new int_type());
        else
            v.emplace_back(new float_type());
    }

    for (int i = 0; i < 900000; i++) {
        std::for_each(v.begin(), v.end(), [](auto &item) { item->inc(); });
    }
}

struct visitor : boost::static_visitor<> {

    template <typename T> void operator()(T &item) { item += 1; }
};

using mytype = boost::variant<int, float>;
void static_test() {
    std::vector<mytype> v;
    for (int i = 0; i < 1024; i++) {
        if (i % 2 == 0)
            v.emplace_back(0);
        else
            v.emplace_back(0.f);
    }

    visitor vi;
    for (int i = 0; i < 900000; i++) {
        std::for_each(v.begin(), v.end(), boost::apply_visitor(vi));
    }
}

template <typename F> double measure(F f) {
    clock_t start = clock();
    f();
    clock_t end = clock();
    float seconds = (float)(end - start) / CLOCKS_PER_SEC;
    return seconds;
}

int main() {
    std::cout << "polymorphism: " << measure([] { dyn_test(); }) << std::endl;
    std::cout << "boost::variant: " << measure([] { static_test(); }) << std::endl;

    return 0;
}    

汇编

gcc

clang+llvm

最佳答案 众所周知,Clang会从各种标准库中错误编译一些std :: vector函数,因为它们的内联中存在一些边缘情况.我不知道这些是否已被修复,但很可能不是.由于unique_ptr比boost :: variant更小更简单,因此它更有可能不会触发这些边缘情况.

您发布的代码实际上是“为什么boost :: variant很棒”.动态分配和随机指针索引除了执行的常规间接指令外?这是一个重大打击(相对).

点赞