4

共有メモリ(ipc)〜48GBと連携する一連のプログラムがあります。

Linux 3.6.0-rc5 で実行されるプログラムは、プレーン C で記述され、コンパイルされた gcc のメイン コンピューターの負荷平均は 6.0 であり、10 秒ごとに 16.0 にジャンプします (24 コア)

0mq (3.2.3、同じネットワーク内の 12 台のマシンから 1000 メッセージ/秒) で他のマシンからデータを受信する 1 つのプロキシ、共有メモリに書き込む 多くの (<50) ワーカーがこのデータを読み取り、いくつかの計算を行います。

約 20% の CPU を使用するプロキシ 1% の CPU を使用するすべてのワーカーは、定期的に 10% ジャンプします。

そのように書かれたすべてのプログラムは、すべての割り当てが init() で行われるときに呼び出されます - プログラムの開始時に呼び出され、destroy() ですべての解放が行われます - 終了前に呼び出されます

malloc/calloc/free をまったく使用しない反復コード。

しかし、両方のプログラムはまだリークしています。1 分あたり約 120 ~ 240 バイト。これは大したことではありません-7〜8日でメモリが使い果たされ、プロセスを開始/停止するだけですが、監視アプリがこの再起動について報告するたびに、リークされたバイトが私の心を食い尽くします:)

悪いこと-共有メモリを使用しているため、valgrindを実行できません-共有メモリの割り当て/アタッチを停止するだけで、すべてがクラッシュし始めます。

このリークを見つけようとして、削除されたバージョンのプロキシを作成しました-リークはありませんが、同じ量のデータをフィードすることはできません。

gdb で実行してもリークはありませんが、速度が約 2/3 に低下したため、このエラーを再現するにはそれほど速くない可能性があります。

したがって、リークの可能性は次のとおりです。

  • 私のコード。ただし、malloc/calloc はありません。ポインタのみ +-、memcpy、memcmp
  • いくつかの標準ライブラリ。glibc? syslog?
  • 多くのソースでの作業で 0mq (1 秒あたり 1k/メッセージはトラフィックが多すぎるとは思わないでください)

そのような状況で役立つ他のツール/ライブラリ/ハックはありますか?

編集: Shivan Raptor がコードについて尋ねました。反復部分は 5k 行の数学です。私が述べたように、割り当てなしで。

ただし、開始、停止、および繰り返しここに入力します。

int main(int argc, char **argv)
{
    ida_init(argc, argv, PROXY);
    ex_pollponies(); // repetive
    ida_destroy();
    return(0);
}


// with some cuttings

int ex_pollponies(void)
{
  int i, rc;
  unsigned char buf[90];
  uint64_t fos[ROLLINGBUFFERSIZE];
  uint64_t bhs[ROLLINGBUFFERSIZE];
  int bfcnt = 0;

  uint64_t *fo;
  uint64_t *bh;

  while(1) {
    rc = zmq_poll(ex_in->poll_items, ex_in->count, EX_POLL_TIMEOUT);
    for (i=0; i < ex_in->count; i++) {
      if (ex_in->poll_items[i].revents & ZMQ_POLLIN) {

        if (zmq_recv(ex_in->poll_items[i].socket, &buf, max_size, 0) == 0)
          continue;
        fo = &fos[bfcnt];
        bh = &bhs[bfcnt];
        bfcnt++;
        if (bfcnt >= ROLLINGBUFFERSIZE)
          bfcnt = 0;

        memcpy(fo, (void *)&buf[1], sizeof(FRAMEOBJECT));
        memcpy(bh, &buf[sizeof(FRAMEOBJECT)+1], sizeof(FRAMEHASH));

        // then store fo, bh into shared memory, with some adjusting and checkings
        // storing every second around 1000 msgs 16 bytes each. But leaking is only 200 bytes per minute.

      }
     }

  }
}

編集2:

私は最終的にvalgrindを機能させました - データの一部(6GB)を使用するだけで、最終的に合格しました。そして、漏れを見つけないでください。しかし、作業の過程で100%のCPUが必要になり、間違いなく私のプログラムはすべての受信データを処理しませんでした-全負荷で動作していません. この半分は私の最後の希望の推測を裏付けました-リークはデータ交換ブロックにあります。mtrace (libc の一部) に関する情報を見つけました。リークの ADDRESS を追跡するのに役立ちました。コードの外側、スレッドの 1 つです。私のコードの唯一のスレッドは、zeromq によって作成されます。次に、ソケットのオプション(hwm、バッファーを増やす)を試してみると、リークの速度が低下しましたが、とてつもなく大きな値でも完全にはなくなりませんでした:(

だから、今、私はそのzeromq漏れを95%確信しています。メールリストで答えを見つけてみてください。

4

1 に答える 1