共有メモリ(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%確信しています。メールリストで答えを見つけてみてください。