我在我的应用程序中广泛使用std::tr1::shared_ptr。这包括将对象作为函数参数传递。请考虑以下内容:
class Dataset {...}
void f( shared_ptr< Dataset const > pds ) {...}
void g( shared_ptr< Dataset const > pds ) {...}
...
使用shared_ptr传递数据集对象可以确保函数f和g内部存在该对象,但这两个函数可能会被调用数百万次,这会导致大量的shared_ptr对象被创建和销毁。以下是最近一次运行的flat gprof分析报告的摘录:
每个样本计为0.01秒。 % 总时间 函数自身 自身 总计 时间(秒) (秒) (秒) 调用次数 每次耗时(s) 每次耗时(s) 名称 9.74 295.39 35.12 2451177304 0.00 0.00 std::tr1::__shared_count::__shared_count(std::tr1::__shared_count const&) 8.03 324.34 28.95 2451252116 0.00 0.00 std::tr1::__shared_count::~__shared_count()
因此,大约17%的运行时间花费在shared_ptr对象的引用计数上。这是正常的吗?
我的应用程序中有很大一部分是单线程的,我正在考虑将一些函数重写为
void f( const Dataset& ds ) {...}
并替换这些调用
shared_ptr< Dataset > pds( new Dataset(...) );
f( pds );
使用
f( *pds );
如果我确定对象在程序流程处于f()内部时不会被销毁,那么可以在这些地方使用智能指针进行传递。但在更改一堆函数签名/调用之前,我想知道通过shared_ptr传递的典型性能损失。似乎不应该将shared_ptr用于经常调用的函数。
欢迎提供任何输入。谢谢阅读。
- Artem
更新: 将一些函数更改为接受 const Dataset&
后,新的配置文件如下:
每个样本计为0.01秒。 % 累计 自身 自身 总数 时间 秒钟 秒钟 调用 s / call s / call名称 0.15 241.62 0.37 24981902 0.00 0.00 std :: tr1 :: __ shared_count ::〜__ shared_count() 0.12 241.91 0.30 28342376 0.00 0.00 std :: tr1 :: __ shared_count :: __ shared_count(std :: tr1 :: __ shared_count const&)
我对析构函数调用次数比复制构造函数调用次数少有些困惑,但总体上,我对相关运行时间的减少非常满意。感谢大家的建议。
gprof
的平面分析报告。 - Artem Sokolov