1

ブースト スレッド固有のポインターを使用して、その特定のスレッドのみのグローバル データを格納しています。以下は、誰かが GetInstance() を呼び出したときに返すシングルトンです。

私の質問は、通常のポインター アクセスと比較して、スレッド固有のポインター (m_tspConnectionManager.get();) を取得するのにかかるおおよその時間です。

以下のコードを使用しました (ここで .get() メソッドを 2 回呼び出します)。完全な関数を実行するのに約 3 秒かかりました。

  typedef boost::thread_specific_ptr<ConnectionManager> ConnMgrPtr;
    static ConnMgrPtr m_tspConnectionManager;
    static ConnectionManager* GetInstance()
            {
                if(!m_tspConnectionManager.get())
                {
                    //first time called by this thread
                    //ConnectionManager* to be used in all subsequent calls from this thread
                    m_tspConnectionManager.reset(new ConnectionManager());
                }
                return m_tspConnectionManager.get();
            }

さて、上記のコードを .get() メソッドを 1 回だけ呼び出すように変更したところ、約 1.9 秒かかりました。

    static ConnectionManager* GetInstance()
            {
                ConnectionManager* pConnMgr = m_tspConnectionManager.get();
                if(pConnMgr == NULL)
                {
                    //first time called by this thread
                    //ConnectionManager* to be used in all subsequent calls from this thread
                    m_tspConnectionManager.reset(new ConnectionManager());
                }
                return pConnMgr != NULL ? pConnMgr : m_tspConnectionManager.get();
            }

したがって、.get() メソッドを呼び出さないだけで、パフォーマンスが 1.1 秒向上することがわかりました。どうやって利益を得るかを理解しようとしてきましたか? 注:このゲインは、GetInstance() 関数を何度も呼び出すことの全体的なゲインである可能性があります。ここでは、単一のコール ゲインを理解しようとしています。

4

1 に答える 1

0

get()時間がかかることはほとんどありません(ただし、もちろん、 NOT を呼び出すよりも遅くなりget()ます。) TLS の「通常の」実装では、オブジェクトは最大で 3 つのポインター間接参照の距離にあります。(スレッド ブロック レジスタ -> TLS ブロック -> ポインタ。) しかし、GetInstance()十分に呼び出している場合、スローダウンは大きなスローダウンになる可能性があります。

がどのくらいの頻度GetInstance()で呼び出されているかを調べます。返されたポインターをキャッシュして、その数を減らしてみてください。もちろん、2 番目の実装は最初の実装よりも望ましいです。

于 2013-11-01T12:43:44.040 に答える