论坛首页 Java企业应用论坛

log4j真的比JDK logger快吗?

浏览 14000 次
精华帖 (0) :: 良好帖 (7) :: 新手帖 (0) :: 隐藏帖 (2)
作者 正文
   发表时间:2009-09-20   最后修改:2009-09-21
OO

这里不想比较这两个日志哪个功能更强,或者是哪个更好用,只是网上说log4j的性能很高想通过自已的方式验证一下。

 

那log4j的性能如果真的高的话,在同等条件下,它究竟比jdk内置的logger快多少呢?这里只比较最常用的文件日志写入速度。

 

最主要是就是这里想不明白,为什么log4j的性能会高呢,log4j的包中并没有包含非java的东东,也就是说没有看到它使用JNI,所以说这里就不太好理解啦,同样使用java的东东,log4j怎么做到比jdk logger快。因为想不明白,所以决定测试一下。

 

刚刚开始时由于对这两个日志实现方式不是太理解,所以走了些弯路,像日志格式没有统一、打印日志分别输出到终端和文件里等等,这里就不再详述,反正过程是痛苦的。

 

测试前期条件为:

1、日志只输出到文件

2、文件的最大大小为1024KB

3、备份文件最多为4个

4、打印消息中没有额外的信息,只是用户打印输出信息,信息写入文件后换行

 

为满足上面的条件,log4j使用如下的配置文件(红色部分为满足上面配置的条件)

log4j.properties 写道
log4j.rootLogger=info, R

log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=log4j/example.log
log4j.appender.R.MaxFileSize= 1024KB
log4j.appender.R.MaxBackupIndex=4

log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%m%n

 

让jdk logger满足上面的条件则在复杂一些,因为jdk的logger没有提供相应的打印输出控制,刚开始想使用java.util.logging.SimpleFormatter来的,但后来发现这个类有明显的性能问题,因为这个格式化输出类每次都会输出打印日志的类名及调用方法名,通过查看jdk LogRecord类的源码,发现通过如下方式实现:

StackTraceElement stack[] = (new Throwable()).getStackTrace();

 也就是说通过异常类获取当前栈信息,再从栈信息中取到调用日志打印的类及该类中的方法。异常处理的开销应该是比较大的,所以说jdk的SimpleFormatter在日志处理上会比较慢。

 

既然不能使用SimpleFormatter类,那我们就重新写一个简单的满足上面测试条件的日志格式化类,如下:

 

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package jdklog;

import java.util.logging.Formatter;
import java.util.logging.LogRecord;

/**
 *
 * @author Administrator
 */
public class MyFormatter extends Formatter{
    
    @Override
    public String format(LogRecord record) {
        StringBuilder b = new StringBuilder();
        b.append(record.getMessage());
        b.append('\n');
        return b.toString();
    }
}

 这个搞好了,还需要关闭jdk logger的终端输出并指定其日志格式化为上面写好的MyFormatter类。这个可以通过修改jre/lib下的logging.properties类完成,我使用的是jdk1.6,修改后的文件像下面这样

jre/lib/logging.properties 写道
handlers= java.util.logging.FileHandler

# Default global logging level.
.level= INFO

# default file output is in user's home directory.
java.util.logging.FileHandler.pattern = %h/java%u.log
java.util.logging.FileHandler.limit = 1048576
java.util.logging.FileHandler.count = 4
java.util.logging.FileHandler.formatter = jdklog.MyFormatter

 因为jdk的大小是按byte算的,所以1024KB=1024*1024byte=1048576,另外我们使用的日志格式化类修改成了新写的MyFormatter类。

 

日志测试时均使用下面的代码进行日志输出:

   for (int i = 0 ; i < Main.MAXSIZE; i++)
        {
            logger.info("This is the " + i + " record");
        }

 

测试结果为:

1万条以下,两者时间基本相同

1~5万条,log4j要较jdk logger快20~50ms

10~100万条,log4j要较jdk logger快100~200ms

200万条时,log4j要较jdk logger快1s

 

总的来说,log4j的性能是要高一些,但是在100万条数据以下优势是不太明显的,而且测试是在循环中调用日志打印的,但是实际情况下应该不会有像上面测试这种短时间内200万条日志写入文件的情况吧?能达到1万条就很多了吧?

 

所以我觉得log4j在性能上是比jdk logger强些,但是相差应该不太,不会成为系统的性能瓶颈。

 

选择哪个还是看用户自己的喜好吧~~~

   发表时间:2009-09-21  
lz严谨求实的精神值得推广,实际测试过才有说服力。

感觉lz测试的过程比结果更有意义,尤其在构建Formatter时付出的心力恰恰体现了log4j的价值,log4j提供了多种appender、formatter等等方便的选择,而并没有因此影响性能,如果用jdk logger要做多少额外的工作可以想象了。
0 请登录后投票
   发表时间:2009-09-22  
log4j 在多个开源项目里都有使用,而且配置更灵活活.
自己搞个小系统之类可以直接使用jdk的日志
0 请登录后投票
   发表时间:2009-09-22  
log4j最大的缺点在于它是静态的,不能通过被注入,如果我想集成写log得老老实实的这样写Log log = LogFactory.getLog(getClass()),很苦闷
0 请登录后投票
   发表时间:2009-09-22  
walle1027 写道
log4j最大的缺点在于它是静态的,不能通过被注入,如果我想集成写log得老老实实的这样写Log log = LogFactory.getLog(getClass()),很苦闷



有点搞笑了...连上个厕所是否都要注入额?
1 请登录后投票
   发表时间:2009-09-22  
ray_linn 写道
walle1027 写道
log4j最大的缺点在于它是静态的,不能通过被注入,如果我想集成写log得老老实实的这样写Log log = LogFactory.getLog(getClass()),很苦闷



有点搞笑了...连上个厕所是否都要注入额?

说得很好,现在好像离开注入就不要活了
0 请登录后投票
   发表时间:2009-09-22  
ray_linn 写道
walle1027 写道
log4j最大的缺点在于它是静态的,不能通过被注入,如果我想集成写log得老老实实的这样写Log log = LogFactory.getLog(getClass()),很苦闷



有点搞笑了...连上个厕所是否都要注入额?

引入注入的目的是为了分离关注点和解除依赖,为什么要在log中注入哪,可以在你的业务逻辑中
0 请登录后投票
   发表时间:2009-09-22  
大家的思维有点发散呀,我做这个测试的主要目的是测试log4j和jdk logger之间的性能差距究竟有多大,因我想既然都是用纯java写的,性能应该差别不大。
至于两个哪个好用应该有好多文章表扬过log4j了,嘿嘿~~~
不过jdk logger也有一些可取地方,像它自带的格式化输出会打印出调用的函数和方法,这个功能虽然有些性能的损失,但是感觉这个挺有用的,和log4j的%F %L有得一拼~~~
0 请登录后投票
   发表时间:2009-09-23  
楼主的精神值得学习
四楼的思维不要被禁锢了,我们使用一个框架有时候只需要使用它对我们开发或者思想带来好处的东西,不能生搬硬套
0 请登录后投票
   发表时间:2009-09-23  
我只想说一句:
log4j可以设置异步打印(org.apache.log4j.AsyncAppender,要提升性能, 请试一下这个), 可以支持log格式为html格式,可以把log配置打印到数据库...
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics