原文地址:http://www.slf4j.org/faq.html#logging_performance

SLF4J supports an advanced feature called parameterized logging which can significantly boost logging performance for disabled logging statement.

For some Logger logger, writing,

logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));

incurs the cost of constructing the message parameter, that is converting both integer i and entry[i] to a String, and concatenating intermediate strings. This, regardless of whether the message will be logged or not.

One possible way to avoid the cost of parameter construction is by surrounding the log statement with a test. Here is an example.

if(logger.isDebugEnabled()) {
  logger.debug("Entry number: " + i + " is " + String.valueOf(entry[i]));
}

This way you will not incur the cost of parameter construction if debugging is disabled for logger. On the other hand, if the logger is enabled for the DEBUG level, you will incur the cost of evaluating whether the logger is enabled or not, twice: once in debugEnabled and once in debug. This is an insignificant overhead because evaluating a logger takes less than 1% of the time it takes to actually log a statement.

Better yet, use parameterized messages

There exists a very convenient alternative based on message formats. Assuming entry is an object, you can write:

Object entry = new SomeObject();
logger.debug("The entry is {}.", entry);

After evaluating whether to log or not, and only if the decision is affirmative, will the logger implementation format the message and replace the '{}' pair with the string value of entry. In other words, this form does not incur the cost of parameter construction in case the log statement is disabled.

The following two lines will yield the exact same output. However, the second form will outperform the first form by a factor of at least 30, in case of a disabled logging statement.

logger.debug("The new entry is "+entry+".");
logger.debug("The new entry is {}.", entry);

two argument variant is also available. For example, you can write:

logger.debug("The new entry is {}. It replaces {}.", entry, oldEntry);

If three or more arguments need to be passed, you can make use of the Object... variant of the printing methods. For example, you can write:

logger.debug("Value {} was inserted between {} and {}.", newVal, below, above);

This form incurs the hidden cost of construction of an Object[] (object array) which is usually very small. The one and two argument variants do not incur this hidden cost and exist solely for this reason (efficiency). The slf4j-api would be smaller/cleaner with only the Object... variant.

Array type arguments, including multi-dimensional arrays, are also supported.

SLF4J uses its own message formatting implementation which differs from that of the Java platform. This is justified by the fact that SLF4J's implementation performs about 10 times faster but at the cost of being non-standard and less flexible.

Escaping the "{}" pair

The "{}" pair is called the formatting anchor. It serves to designate the location where arguments need to be substituted within the message pattern.

SLF4J only cares about the formatting anchor, that is the '{' character immediately followed by '}'. Thus, in case your message contains the '{' or the '}' character, you do not have to do anything special unless the '}' character immediately follows '}'. For example,

logger.debug("Set {1,2} differs from {}", "3");

which will print as "Set {1,2} differs from 3".

You could have even written,

logger.debug("Set {1,2} differs from {{}}", "3");

which would have printed as "Set {1,2} differs from {3}".

In the extremely rare case where the the "{}" pair occurs naturally within your text and you wish to disable the special meaning of the formatting anchor, then you need to escape the '{' character with '\', that is the backslash character. Only the '{' character should be escaped. There is no need to escape the '}' character. For example,

logger.debug("Set \\{} differs from {}", "3");

will print as "Set {} differs from 3". Note that within Java code, the backslash character needs to be written as '\\'.

In the rare case where the "\{}" occurs naturally in the message, you can double escape the formatting anchor so that it retains its original meaning. For example,

logger.debug("File name is C:\\\\{}.", "file.zip");

will print as "File name is C:\file.zip".

What is the fastest way of (not) logging?的更多相关文章

  1. Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory

    学习架构探险,从零开始写Java Web框架时,在学习到springAOP时遇到一个异常: "C:\Program Files\Java\jdk1.7.0_40\bin\java" ...

  2. Oracle补全日志(Supplemental logging)

    Oracle补全日志(Supplemental logging)特性因其作用的不同可分为以下几种:最小(Minimal),支持所有字段(all),支持主键(primary key),支持唯一键(uni ...

  3. Java程序日志:java.util.logging.Logger类

    一.Logger 的级别 比log4j的级别详细,全部定义在java.util.logging.Level里面.各级别按降序排列如下:SEVERE(最高值)WARNINGINFOCONFIGFINEF ...

  4. python 学习笔记 -logging模块(日志)

    模块级函数 logging.getLogger([name]):返回一个logger对象,如果没有指定名字将返回root loggerlogging.debug().logging.info().lo ...

  5. python logging colorlog

    import logging LOG_LEVEL = logging.NOTSET LOGFORMAT = "[%(log_color)s%(levelname)s] [%(log_colo ...

  6. [转]ASP.NET Core 开发-Logging 使用NLog 写日志文件

    本文转自:http://www.cnblogs.com/Leo_wl/p/5561812.html ASP.NET Core 开发-Logging 使用NLog 写日志文件. NLog 可以适用于 . ...

  7. python 之 logging

    #coding=utf-8 import logging logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(filename ...

  8. Python Logging模块的简单使用

    前言 日志是非常重要的,最近有接触到这个,所以系统的看一下Python这个模块的用法.本文即为Logging模块的用法简介,主要参考文章为Python官方文档,链接见参考列表. 另外,Python的H ...

  9. python模块(shelve,xml,configparser,hashlib,logging)

    1.1shelve模块 shelve 模块比pickle模块简单,只有一个open函数,返回类似字典对象,可读可写:key必须为字符串, 而值可以是python所支持的数据类型. shelve模块主要 ...

随机推荐

  1. c++输出保留固定小数位数

    cout<<setprecision(6)<<fixed<<ans<<endl;

  2. Delphi 中的自动释放策略

    来自万一老师的博客:http://www.cnblogs.com/del/archive/2011/12/21/2295794.html ------------------------------- ...

  3. tomcat已启动,使用maven的deploy发布后,根据路径打开浏览器访问时报错HTTP Status 500 - Error instantiating servlet class

    web项目中请求出现错误,如下: HTTP Status 500 - Error instantiating servlet class XXXX类 type Exception report mes ...

  4. pymongo的一些操作

    参考:http://www.yiibai.com/mongodb/mongodb_drop_collection.html http://www.cnblogs.com/zhouxuchen/p/55 ...

  5. <<Javascript Patterns>>阅读笔记 -- 第2章 基本技巧(一)

    第一次写这种东西, 有些生涩和蹩脚, 也是为了自己在表达或是总结方面有所提高, 同时为看过的东西留个痕迹, 以便日后查阅. 有错误或是不妥的地方, 还望各位指正, 谢谢! 第1章 简介 本章主要介绍了 ...

  6. lr_start_timer,lr_get_transaction_duration,lr_get_transaction_wasted_time函数使用总结

    lr_start_timer: 函数的功能: 为了计算时间更加精确,可以用这个函数去掉LR自身的检查点所浪费的时间.如text check and image time Action() { doub ...

  7. HashMap在Java1.7与1.8中的区别

    基于JDK1.7.0_80与JDK1.8.0_66做的分析 JDK1.7中 使用一个Entry数组来存储数据,用key的hashcode取模来决定key会被放到数组里的位置,如果hashcode相同, ...

  8. logstash通过tcp收集日志

    (1)标准输入输出tcp模块 1.修改配置文件 #vim /etc/logstash/conf.d/tcp.conf input { tcp { port => "5600" ...

  9. JavaScript 实现数组去重

    JavaScript 实现数组去重 演示Demo 数组去重 // 方法一 function unique1(a) { var res = []; for (var i = 0, len = a.len ...

  10. python 什么是全局解释器锁GIL

    什么是全局解释器锁GIL Python代码的执行由Python 虚拟机(也叫解释器主循环,CPython版本)来控制,Python 在设计之初就考虑到要在解释器的主循环中,同时只有一个线程在执行,即在 ...