1

非同期ロギング クラスを作成しようとしていますが、いつログをファイルに書き込むかを決定できません。

現在、すべてのログをベクトルに保存し、タイムスタンプで並べ替えることを考えています。

問題は、いつログをファイルに書き込む必要があるかということです。ディスクに書き込む前に N 個のログを待機すると、ログ エントリが失われるか、ベクトル内のログが既に N 個に達している場合、ログ エントリが順不同でログに書き込まれる可能性があります。

何らかのタイマーを使用することを考えていましたが、それがより良いかどうかはわかりません。

アイデアをいただければ幸いです、ありがとう。

4

2 に答える 2

0

バッファリング(または明示的なフラッシュ)なしで順不同で書くというコメントに同意します。ただし、それらを順番に書きたい場合は、書き込みを管理する別のスレッドを用意します。遅延到着をカバーすることを合理的に保証できる特定の遅延量 (おそらく秒単位) を定義します。

したがって、非常に基本的な意味で、スレッド関数は次のようになります。

time_t writeDelay = 10;  // 10 seconds

for(;;)
{
    // Sleep for a second
    //[OS-specific code here]

    time_t now;
    time(&now);
    WriteLogEntriesUpTo(now - writeDelay);
}

ここでの問題は、ログ エントリをベクトルに並べ替えると、正しく行わないと、ロガーに多くのオーバーヘッドが発生する可能性があることです。少なくとも a を使用すると、dequeエントリを前面から簡単にポップできます。これを行うとしたら、ログ文字列とキュー内の単純なレコード用に大きなバッファー (実質的にはメモリ プール) を持つという道をたどるでしょう。タイムスタンプとポインターを使用すると、並べ替えが簡単になります。

struct LogEntry {
    time_t timestamp;
    char *message;
};

これらを に配置する代わりに、dequeある種の順序付きリストを実装します (これもメモリ プール)。これをすべて高速化するのは非常に面倒です。考えれば考えるほど、順不同で書くことが理にかなっています。

于 2012-09-12T02:00:50.427 に答える
0

非同期ログを扱っている場合は、スレッドセーフ キューを使用して、タイムスタンプ付きのすべてのメッセージをログ スレッド ワーカーに送り込むことをお勧めします。ロギング ワーカーは、ブロック内のすべてのメッセージがキューに表示されるときに処理できます。

このスレッド セーフなキューの抽象化により、バッファー サイズを設定するか、または無制限のままにしておくことができます (条件変数を介してキュー/バッファーがいっぱいになった場合にスレッドにメッセージを送ることができます)。多くのスレッドから同時にログを記録し、エラーが発生した後でもログを処理します。ロガーが終了する前に終了するのを待つ try catch ループでメイン スレッドをラップします (セグメンテーション違反には役立ちませんが、ほとんどのエラーには役立ちます)。さらに、メッセージをロガーにパントし、IO 操作を待機することなくメイン プログラム スレッドに進むことができます (実行時間の大幅な短縮につながる可能性があります)。また、実装も難しくありません。キューの API は非常に限られているため、データ構造とのやり取りは、スコープ付きロックでリストをラップするだけです。

この実装には少額の代償がかかります。つまり、固定価格です。ただし、他のマルチスレッドを追加する必要がある場合は、ロガーを再構築する必要はなく、IO を別のスレッドにオフロードすることで、おそらくシングル スレッドのロガーよりも高速になります。

メッセージの順序が正しくない場合は、2 つのオプションがあります。キューのログ ワーカー側でログの並べ替えを行います (ワーカーが古いメッセージを保持するためのローカル バッファーを保持します)。または、タイムスタンプを使用してメッセージを並べ替え、挿入時に少し高い価格を支払うことを使用して、ログ キューの実装を優先キューに変更します。後者はおそらく実装が簡単ですが、より高い同期代価を支払います。

Boostスレッドを使用してC++でこの戦略を使用しましたが、非常にうまく機能します。クラッシュしても、クラッシュの直前からログを取得できます。作業をさまざまなスレッドに分岐して、簡単に並列化できる作業を行うときは、イベントの順序を簡単に追跡できるように、どこでも同じログ抽象化を使用するだけです。

于 2012-09-12T16:59:29.187 に答える