Log4jに次のように記述した場合
**logger.debug("Processing trade with id: " + id + " symbol: " + symbol);**
文字列プールに文字列を作成しますが、slf4jを使用するときは、このようなパラメーターを使用します
**logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);**
これら2つのステートメントの違いは何ですか、slf4jは実行時にStringを作成しますか?
違いはパフォーマンスの向上です。log4jでは、ログレベルがdebugより低い場合でも、行が評価されるたびに文字列が連結されるため、文字列は使用されません。
slf4jでは、文字列とパラメーターはロガーに渡され、ログメッセージが実際に使用される場合にのみロガーに置き換えられます。
数行ごとにデバッグステートメントを含むコードを想像してください。運用中およびデバッグが無効になっている場合、これは使用されない大量の文字列操作です。
String concatenations
を減らすことでパフォーマンスを向上させたいと思います。
これを書くとき
"Processing trade with id: " + id + " symbol: " + symbol
印刷文字列を手動で作成しています。
書くとき
"Processing trade with id: {} and symbol : {} ", id, symbol
-------^id------------^symbol---------
内部的に印刷する前の2番目の方法slf4j
が維持され、連結された新しい文字列が再度生成されます(Havenはソースコードをチェックせず、StringBuilder
である場合があります)。
{}
はプレースホルダーとして呼び出され、ユーザーから渡された引数に置き換えられます。
この形式は、ロガーがDEBUGレベルで無効になっているときに、余分な文字列の連結を回避します。ただし、このバリアントは、このロガーがDEBUGに対して無効になっている場合でも、メソッドを呼び出す前にObject []を作成するという隠れた(そして比較的小さな)コストを負います。この隠れたコストを回避するためだけに、1つと2つの引数を取るバリアントが存在します。
フォーマットの使用方法を読む: ScalaでJava.String.formatを使用する方法
SLF4Jは基本的に抽象化レイヤーです。ロギングの実装ではありません。つまり、ライブラリを作成していてSLF4Jを使用している場合、そのライブラリを他の誰かに使用してもらうことができ、SLF4Jで使用するロギング実装を選択できます。 log4jまたはJavaロギングAPI。プロジェクトに依存しているライブラリを使用しているという理由だけで、プロジェクトが多くのロギングAPIに依存するのを防ぐのに役立ちます。
Log4j2 APIを使用すると、logger.info( "String:{} int:{}。"、 "Hello、World"、10);
これら2つのステートメントの違いは何ですか、slf4jはラムの時間に文字列を作成しますか?
文字列は、log4jを使用するかsl4jを使用するかに関係なく作成されます。 sl4jはプレースホルダーの利便性を提供しています。
文字列の連結についてです。 1行目は常にStringを連結し、その負荷の高い操作を行い、2行目はログレベルがデバッグと一致しない場合は連結しません。 StringBuilderの内部使用のために、ログレベルの2番目のオプションを一致させるとパフォーマンスが向上する可能性があるとは思いません。