既存のロギング ライブラリを拡張しています。これは 2 つの側面を持つシステムです。フロントエンドはタスクがログ メッセージを書き込む場所であり、バックエンドはアプリケーションがそれらのメッセージを異なるシンクに転送するリスナーを接続できる場所です。バックエンドは 1 つのハードワイヤード リスナーでしたが、現在は柔軟性のためにこれを拡張しています。このコードは、高性能(1 ミリ秒あたりの転送バイト数で測定) が非常に重要な設計および実装目標である組み込みデバイスでのみ使用されます。
パフォーマンス上の理由から、メッセージはバッファリングされ、転送はバックグラウンド タスクで行われます。そのタスクは、キューからメッセージのチャンクをフェッチし、それらをすべてフォーマットしてから、登録された関数を介してリスナーに渡します。これらのリスナーはメッセージをフィルター処理し、フィルター基準に合格したメッセージのみをシンクに書き込みます。
これを考えると、メッセージをN
送信するための通知関数 (リスナー) を持つことになります。これはかなり古典的な問題です。ここで、2 つの可能性があります。メッセージをループしてから、メッセージをそれぞれに渡す通知関数をループします。M
N*M
for(m in formatted_messages)
for(n in notification_functions)
n(m);
void n(message)
{
if( filter(message) )
write(message);
}
または、すべての通知関数をループして、一度にすべてのメッセージを渡すこともできます。
for(n in notification_functions)
n(formatted_messages);
void n(messages)
{
for(m in messages)
if( filter(m) )
write(m);
}
どの設計がより多くのメッセージをタイム スライスごとに処理できる可能性が高いかについて、基本的な考慮事項はありますか? (この質問がリスナーのインターフェースをどのように決定するかに注意してください。これはマイクロ最適化の質問ではなく、パフォーマンスを妨げない設計を作成する方法に関する質問です。私が測定できるのはずっと後のことであり、リスナーのインターフェースを再設計するには費用がかかります。 .)
私がすでに行ったいくつかの考慮事項:
- これらのリスナーはメッセージをどこかに書き込む必要がありますが、これはかなりコストがかかります。そのため、関数呼び出し自体はパフォーマンス面でそれほど重要ではない可能性があります。
- すべてのケースの 95% で、リスナーは 1 つだけになります。