C++ 提高共享ptr解引用成本

C++ 提高共享ptr解引用成本,c++,boost,shared-ptr,C++,Boost,Shared Ptr,我试图比较原始指针、boost shared_ptr和boost弱_ptr之间的性能。在解引用部分,我期望shared_ptr和raw_ptr相等,但结果表明shared_ptr的速度大约是前者的两倍。对于测试,我创建了一个数组,其中包含指向int的指针或共享指针,然后在循环中取消引用,如下所示: int result; for(int i = 0; i != 100; ++i) { for(int i = 0; i != SIZE; ++i) result += *array[i]

我试图比较原始指针、boost shared_ptr和boost弱_ptr之间的性能。在解引用部分,我期望shared_ptr和raw_ptr相等,但结果表明shared_ptr的速度大约是前者的两倍。对于测试,我创建了一个数组,其中包含指向int的指针或共享指针,然后在循环中取消引用,如下所示:

int result;
for(int i = 0; i != 100; ++i)
{
  for(int i = 0; i != SIZE; ++i)
    result += *array[i];
}
测试的完整代码可在此处找到:

无断言优化构建的测试时间可在此处找到:

感兴趣的价值是“解除共享时间”和“解除共享时间”

我猜这个测试可能有点缺陷,但我没能找出区别的来源。分析显示,来自shared_ptr的操作符*被内联,这似乎需要更多的时间。我仔细检查了boost断言是否已关闭

如果有人能解释差异的来源,我将不胜感激

附加独立测试:

正如艾伦·斯托克斯(Alan Stokes)在评论中所说,这是由于缓存效应。共享指针包含一个引用计数,这意味着它们在内存中比原始指针大。当存储在连续数组中时,每个缓存线得到的指针更少,这意味着循环必须比原始指针更频繁地输出到主内存

您可以通过在原始指针测试中分配
SIZE*2
整数来观察此行为,但也可以将反引用循环更改为按
i+=2
而不是
++i
跨步。这样做在我的测试中产生了大致相同的结果。我的原始测试代码如下

#include <iostream>
#include <boost/timer.hpp>

#define SIZE 1000000

typedef int* PtrT;

int do_deref(PtrT* array)
{
    int result = 0;
    for(int i = 0; i != 1000; ++i)
    {
        for(int i = 0; i != SIZE*2; i+=2)
            result += *array[i];
    }

    return result;
}

int main(void)
{
    PtrT* array = new PtrT[SIZE*2];
    for(int i = 0; i != SIZE*2; ++i)
        array[i] = new int(i);
    boost::timer timer;
    int result = do_deref(array);
    std::cout << "deref took " << timer.elapsed() << "s" << std::endl;
    return result;
}
我的结果(x86-64 Unbuntu 11虚拟机):


+前几天我也在想这个。缓存效果?shared_ptr比原始指针大,因此您的数组将覆盖更多缓存线,并且需要更长的读取时间。您在哪个平台上运行这些测试?为什么是指针数组?你不应该多次取消引用同一个指针吗?@BartJanssens:我会通过的。经常性的批评比建设性的批评容易“共享指针包括一个引用计数”,实际上是一个指向数据结构的指针,包含2个引用计数、一个指针、一个删除器,甚至可能还有一个互斥体(希望不是)。@大小是2个指针-一个指向实际负载,一个指向开销。但这些都不会影响简单威慑的成本。啊,非常感谢!我将调整我的测试,使比较更加公平。
#include <iostream>
#include <boost/timer.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#define SIZE 1000000

typedef boost::shared_ptr<int> PtrT;

int do_deref(PtrT* array)
{
    int result = 0;
    for(int j = 0; j != 1000; ++j)
    {
        for(int i = 0; i != SIZE; ++i)
            result += *array[i];
    }

    return result;
}

int main(void)
{
    PtrT* array = new PtrT[SIZE];
    for(int i = 0; i != SIZE; ++i)
        array[i] = boost::make_shared<int>(i);
    boost::timer timer;
    int result = do_deref(array);
    std::cout << "deref took " << timer.elapsed() << "s" << std::endl;
    return result;
}
Original Raw: 6.93
New Raw: 12.9
Original Shared: 12.7
New Shared: 10.59