正如阿兰·斯托克斯在他的评论中说,这是由于缓存的影响。共享指针包含引用计数,这意味着它们在内存中的体积比原始指针大。当存储在一个连续的数组中时,每个缓存行的指针就会减少,这意味着循环必须比原始指针更经常地出到主存储器。
您可以在原始指针测试中分配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;
}
顺便提及,使用boost::make_shared<int>(i)
代替PtrT(new int(I))
在存储器而不是在不同的地点一起分配的引用计数和对象。在我的测试中,这改善了共享指针取消引用的性能约10-20%。代码是如下:
#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;
}
我的结果(x86-64的Unbuntu 11 VM):
Original Raw: 6.93
New Raw: 12.9
Original Shared: 12.7
New Shared: 10.59
+1,我想在今天的一天了。 –
缓存效果? shared_ptr比原始指针大,所以你的数组将覆盖更多的缓存行并花费更长的时间来读取。 –
你在哪些平台上运行这些测试? – SoapBox