共享指针和性能

Gue*_*est 8 c++ performance memory-management cpu-usage shared-ptr

我现在一直在使用共享指针,我的程序中存在性能问题...所以我想知道共享指针是否导致性能下降.如果是这样,那有多难?非常感谢.

我的程序是多线程的,使用std :: tr1 :: shared_ptr

pga*_*ast 13

如果您的应用程序传递的是大约700字节的XML消息,这些消息可能包含在65字节的Google协议消息或85字节的ASN.1消息中,那么它可能无关紧要.但是,如果它每秒处理一百万个事件,那么我不会忽略在传递指针时添加2个完整读取修改写入(RMW)周期的成本.

完全读取修改写入大约为50 ns,因此两次为100 ns.这个成本是lock-inc和lock-dec的成本 - 与2 CAS相同.这是Windows关键部分保留和释放的一半.这与单个机器周期推送相比(2.5GHZ机器上400 PICO秒)

这甚至不包括使实际包含计数的缓存行无效的其他成本,BUS锁对其他处理器的影响等.

通过const引用传递智能指针几乎总是首选.如果被调用者在想要保证或控制指针对象的生命周期时没有创建新的共享指针,那么它就是被调用者中的错误.通过线程安全引用计数智能指针的价值只是要求性能命中.

使用引用计数指针毫无疑问简化了生命周期,但是通过值传递共享指针来尝试防止被调用者中的缺陷是纯粹和完全无意义的.

过度使用引用计数可以在短时间内将一个可以处理1毫米每秒消息(mps)的细小程序变成一个在同一硬件上处理150k mps的胖程序.突然之间你需要半个机架的服务器和10000美元/年的电力.

如果您可以在没有引用计数的情况下管理对象的生命周期,那么总是会变得更好.

一个简单改进的一个例子就是说,如果你要扇出一个对象并且你知道扇出的宽度(比如n)增加n而不是每个扇出时单独递增.

顺便说一句,当cpu看到一个锁定前缀时,它确实说"哦,不会这会伤害".

所有这一切,我同意每个人你应该验证热点.


Jar*_*Par 10

鉴于数据,几乎不可能正确回答这个问题.真正告诉应用程序中导致性能问题的唯一方法是在程序上运行探查器并检查输出.

话虽这么说,但是shared_ptr导致减速的可能性很小.shared_ptr类型和许多早期本土变种用于越来越多的C++程序.我自己在工作中使用它们(在家里专业).我花了很多时间来分析我的工作应用程序,而shared_ptr甚至没有接近我的代码或应用程序中运行的任何其他代码中的问题.这个错误更有可能发生在其他地方.


Jer*_*fin 5

共享指针是引用计数的。特别是当您使用多线程时,增加和减少引用计数可能会花费大量时间。多线程在这里受到伤害的原因是,如果您在线程之间传递共享指针,引用计数最终将在这些线程之间共享,因此任何操作都必须在线程之间同步。这可能会减慢速度。

编辑:对于那些关心多慢的线程互锁可以进行一些相当简单的操作的人,请参阅 Herb Sutter 对CoW Strings的一些实现的测试。尽管他的测试远非完美(例如,他仅在 Windows 上进行了测试),但它仍然提供了一些关于您可以预期的速度减慢的想法。对于大多数实际目的,您可以/可以将 CoW 字符串视为类似 a 的东西shared_ptr<charT>,并添加了许多(不相关的)成员函数。

  • 他没有说他正在使用什么 shared_ptr。有些已经是线程感知的,有些则不是。他正在使用的是否是一个值得怀疑的问题。也就是说,您肯定是对的,这是导致性能问题的原因的可能性很小。 (2认同)
  • 当然,我没有对他的程序进行概要分析,并且将性能问题归咎于 shared_ptr 而不这样做是推测。然而,这不是他问的问题。他问的是 shared_ptr 是否会导致速度变慢,如果会,会导致速度变慢。答案是“是的,他们可以,但具体有多少几乎无法预测。” 我同意他们可能不是他问题的根源,但这不是他要问的。 (2认同)

Mik*_*vey 5

如果您的程序似乎存在性能问题,那么开始猜测问题可能是完全自然的,但如果您想下注,则几乎100%可能完全是其他问题.分析可能会发现问题.这是我使用的方法.