簡體   English   中英

weak_ptr 的性能損失是什么?

[英]What's the performance penalty of weak_ptr?

我目前正在為游戲設計一個對象結構,在我的案例中,最自然的組織變成了一棵樹。 作為智能指針的忠實粉絲,我只使用shared_ptr 但是,在這種情況下,樹中的子節點將需要訪問它的父節點(例如——地圖上的生物需要能夠訪問地圖數據——因此他們的父節點的數據。

擁有的方向當然是地圖擁有它的存在,因此擁有指向它們的共享指針。 然而,要從存在中訪問地圖數據,我們需要一個指向父級的指針——智能指針的方式是使用引用,即weak_ptr

然而,我曾經讀到鎖定weak_ptr是一項昂貴的操作——也許這不再是真的——但考慮到weak_ptr會經常被鎖定,我擔心這種設計注定會導致性能不佳。

因此問題是:

鎖定weak_ptr 的性能損失是什么? 它有多重要?

來自 Boost 1.42 源代碼( <boost/shared_ptr/weak_ptr.hpp>第 155 行):

shared_ptr<T> lock() const // never throws
{
    return shared_ptr<element_type>( *this, boost::detail::sp_nothrow_tag() );
}

因此,James McNellis 的評論是正確的; 這是復制構造shared_ptr的成本。

對於我自己的項目,我能夠通過在任何 boost 包含之前添加#define BOOST_DISABLE_THREADS來顯着提高性能。 這避免了 weak_ptr::lock 的自旋鎖/互斥開銷,這在我的項目中是一個主要瓶頸。 由於該項目不是多線程 wrt boost,我可以做到這一點。

使用/取消引用shared_ptr幾乎就像訪問原始 ptr,與常規指針訪問相比,鎖定weak_ptr是一種性能“重”操作,因為此代碼必須“線程感知”才能正常工作,以防萬一另一個線程觸發釋放指針引用的對象。 至少,它必須執行某種互鎖/原子操作,根據定義,這種操作比常規內存訪問慢得多。

像往常一樣,查看發生了什么的一種方法是檢查生成的代碼

#include <memory>

class Test
{
public:
    void test();
};

void callFuncShared(std::shared_ptr<Test>& ptr)
{
    if (ptr)
        ptr->test();
}

void callFuncWeak(std::weak_ptr<Test>& ptr)
{
    if (auto p = ptr.lock())
        p->test();
}

void callFuncRaw(Test* ptr)
{
    if (ptr)
        ptr->test();
}

通過 shared_ptr 和原始指針訪問是一樣的。 由於shared_ptr是作為引用傳遞的,我們需要加載引用的值,這就是為什么shared_ptr版本的區別只是一個額外的加載。

callFuncShared:

在此處輸入圖片說明

callFuncWeak:

在此處輸入圖片說明

通過weak_ptr調用會產生10 倍的代碼,並且它最多必須通過鎖定的比較交換,這本身將比取消引用raw 或shared_ptr 花費10 倍以上的CPU 時間:

在此處輸入圖片說明

只有當共享計數器不為零時,它才能加載指向實際對象的指針並使用它(通過調用對象,或創建shared_ptr )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM