2016-10-31 29 views
3

我需要優化一些遺留代碼,並且對於C++來說相當新穎。用於高性能FIFO的C++容器

該代碼在兩個線程中執行網絡數據包處理,一個線程將數據包推送到FIFO [topupBuffer],另一個線程從隊列中讀取數據並將它們從IP套接字[writeToIPOutput]發送出去。遺留代碼使用std :: deque來實現FIFO。

但是,運行該程序會使用大量的CPU,高達50%(其中它需要更像5%)。運行gprof似乎揭示了std::deque是罪魁禍首。 (我不知道我是正確的解釋剖析結果,因此幫助表示讚賞)從配置文件輸出

節選: topupBuffer層次:

index % time self children called  name 
       0.65 2.51  1/1   DvIPFilePlayback::topupBufferThreadMethod(void*) [2] 
[1]  60.5 0.65 2.51  1   DvIPFilePlayback::topupBuffer() [1] 
       0.27 1.15 4025575/4025575  DvIPPlaybackBC::bufferizeTsPackets(TPlaybackBuffer&, int&, int&) [5] 
       0.03 0.56 4026668/4026668  std::deque<TTsPacket, std::allocator<TTsPacket> >::push_back(TTsPacket const&) [6] 
       0.03 0.15 4046539/5749754  std::deque<TPlaybackBuffer, std::allocator<TPlaybackBuffer> >::size() const [17] 

[5]  27.2 0.27 1.15 4025575   DvIPPlaybackBC::bufferizeTsPackets(TPlaybackBuffer&, int&, int&) [5] 
       0.04 0.30 4031674/4031674  std::deque<TTsPacket, std::allocator<TTsPacket> >::pop_front() [11] 
       0.03 0.30 8058004/8058004  std::deque<TTsPacket, std::allocator<TTsPacket> >::size() const [12] 
       0.01 0.19 576183/576183  DvPlaybackBC::insertToPlaybackBuffer(TPlaybackBuffer const&) [22] 
       0.04 0.11 4029401/4029401  std::deque<TTsPacket, std::allocator<TTsPacket> >::front() [25] 

writeToIPOutput Hierarchy

[3]  36.8 0.92 1.00  1   DvIPPlaybackBC::writeToIPOutput() [3] 
       0.31 0.00 1129444/1129444  TPlaybackBuffer::operator=(TPlaybackBuffer const&) [13] 
       0.01 0.18 579235/1155128  std::deque<TPlaybackBuffer, std::allocator<TPlaybackBuffer> >::push_back(TPlaybackBuffer const&) [8] 
       0.03 0.10 1135318/1135318  std::deque<TPlaybackBuffer, std::allocator<TPlaybackBuffer> >::pop_front() [27] 

我猜writeToIPOutput花太多的時間在作業上。我可以解決這個問題。但topupBuffer花費的時間在std::deque

這是配置文件輸出的正確解釋嗎?

如果是這樣,那麼使用不同的容器會更有效率,如果是這樣,哪一個呢?

感謝您在調用樹結束

編輯我 的解釋性說明說:

% time This is the percentage of the `total' time that was spent 
     in this function and its children. Note that due to 
     different viewpoints, functions excluded by options, etc, 
     these numbers will NOT add up to 100%. 

self This is the total amount of time spent in this function. 

children This is the total amount of time propagated into this 
     function by its children. 

所以看着bufferizeTsPackets,1.15花費在其子,其中,0.30 + 0.30 + 0.11 = 0.71用於不同的deque方法(push_back,size等)。對?因此,0.71超過在兒童中花費的總時間(1.15)的一半(??)

+0

您是否嘗試過使用我們心愛的朋友,['std :: vector'](http://en.cppreference.com/w/cpp/container/vector)?對於先進先出,雖然是平凡的,但你可能想考慮['std :: queue'](http://en.cppreference.com/w/cpp/container/queue)作爲底層容器的向量 – WhiZTiM

+0

我想知道一個['boost :: lockfree :: queue'](http://www.boost.org/doc/libs/1_59_0/doc/html/boost/lockfree/queue.html)會更好。 – NathanOliver

+0

嘗試使'deque'中的每個項目成爲工作項目的簡短向量,這樣您就不必在共享數據結構上執行多少操作。 –

回答

0

更有效的結構是使用數組實現循環隊列(環形緩衝區)。

由於數組的大小是固定的,所以您必須使數組足夠大以免沒有數據超限;或者只存儲最後的N個值,其中N是緩衝區的容量。

許多嵌入式系統使用陣列來減少由動態內存位置導致的內存碎片問題。

如果您的陣列足夠小,它可以放入處理器的數據緩存中;這加速了計算。

+0

經過很長一段時間的擺弄之後,我實現了一個固定大小的C型陣列,它擁有結構並在界面使其看起來像一個雙耳。現在好多了! – Danny