2016-10-31 12 views
3

従来のコードを最適化する必要があり、C++にはかなり新しいです。高性能FIFO用のC++コンテナ

このコードは、パケットをFIFO [topupBuffer]にプッシュし、もう一方のスレッドがキューから読み取り、IPソケット[writeToIPOutput]を送信する2つのスレッドでネットワークパケット処理を行います。従来のコードでは、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] 

プロファイル出力から

exceptsで(ヘルプは高く評価されるように私は、私が正しく、プロファイル結果を解釈していますわかりません) writeToIPOutput階層

[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にあります。

プロファイル出力の正しい解釈は正しいですか?

もしそうなら、より効率的になる別のコンテナを使用していますか?

コールツリーの最後にI 注釈が言うあなたに

EDITありがとう:だからbufferizeTsPackets見て

% 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. 

、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)を使ってみましたか? FIFOについては、世俗的ですが、ベクターを基にしたコンテナとして['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スタイルの配列を実装し、 dequeのように見えるようにするインタフェース。今はるかに良い! – Danny