web-dev-qa-db-ja.com

slf4jに引数を渡す正しい方法はありますか?

情報をトレースするためにslf4jを使用しています。私のコードは

private static final Logger log = LoggerFactory.getLogger(ObjectTest.class);

log.trace("Time taken to store " + count
            + " objects of size " + size +  " is " + (time) + " msecs");

log.trace("Time taken to store {} objects of size {} is {} msecs",
        new Object[] { count, size, time });

log.trace("Time taken to store {} objects of size {} is {} msecs",
        count, size, time);

トレースを記録するための好ましいメカニズムです。

43
diya

3が最高です。

3と2は同じ(またはほぼ同じ)バイトコードを生成しますが、3は入力が簡単で短いため、3は2よりも優れています。

トレースが有効になっていない場合、1は文字列の連結(「保存にかかる時間」+カウント+ ....)を実行する必要がありますが、2はトレースが有効な場合にのみ文字列の連結を行います。 1。

51
sbridges

3は、SLF4J 1.6.xでサポートされていないことを除いて最適です。 3つ以上の引数の場合、2番目の形式が必要です。 3番目の形式は、1つまたは2つの引数でのみ機能します(3つ以上ではありません)。

SLF4J 1.7の時点で、3番目の形式も3つ以上の引数でサポートされるようになりました。 Javaコンパイラは、3つ以上の引数を持つ呼び出しを2番目のフォームにサイレントに変換し、Object []を印刷メソッドに渡します。これは、Javaこれにより、SLF4J 1.7はSLF4J 1.6と100%互換になります。

30
Ceki

3番目のバリアントが最適です。

実際、最初のケースは、StringBuilderによる文字列の連結です。

2番目と3番目のケースは同じです。整数値を整数(または他のオブジェクト)にボックス化し、それらをパックする配列を作成する必要があります。

私のマシンでの簡単なテストでは、ロギングが実行されなかった場合(56ns対459ns)の場合、3番目のバリアントの方が約8倍優れていると言われています。

public class LogTest {
    private static final Logger logger = LoggerFactory.getLogger(LogTest.class);

    public static void main(String[] args) {
        int size = 100_000_000;

        long start = System.nanoTime();
        for (int i = 0; i < size; i++) {
            logger.trace("1 {} 2 {} 3 {}", i, i, i);
        }
        System.out.println((System.nanoTime() - start) / size);

        start = System.nanoTime();
        for (int i = 0; i < size; i++) {
            logger.trace("1 " + i + " 2 " + i + " 3 " + i);

        }
        System.out.println((System.nanoTime() - start) / size);
    }
}
7