近日在写多线程方面的东西,需要对多线程进行日志监控就重新翻出了log4j,看到了log4j下居然还有一个AsyncAppender,异步记日志?觉得挺不错,网上搜了一下也有一些讨论,JavaEye上也有很多讨论。但是这个AsyncAppender到底能否提升日志性能呢?我们还是先看看log4j本身文档里的性能测试说明吧,详细测试数据见如下URL:http://www.ingrid.org/jajakarta/log4j/jakarta-log4j-1.1.3/docs/api/org/apache/log4j/performance/Logging.html
由此可见AsyncAppender虽然是异步的,但是并不能提升性能,为什么呢?何谓异步?异步就是另外开了个线程用来专门记录日志,然而既然引入了多线程,线程间的同步开销就不能不考虑了,看AsyncAppender的源代码中到处充斥着synchronized就能看到了。
用独立线程处理日志会引入以下几个问题:
- 中断(如果一个阻塞在日志操作的线程被中断,还出现什么情况?)
- 服务担保(logger能保证成功加入队列的消息都能在服务终止前被记录么?)
- 饥饿策略(当生产者记录消息比logger线程的处理能力更快的时候会如何?)
- 服务的生命周期(如何关闭logger,如何就服务的状态与生产者进行沟通?)
由此的需要讨论就是,为什么要使用异步?何时使用异步?如何使用异步?我们先来看同步和异步到底有何不同:
同步情况
各线程直接获得输出流进行输出(线程间不需要同步)。
异步情况
- 各线程将日志写到缓存,继续执行下面的任务(这里是异步的)
- 日志线程发现需要记日志时独占缓存(与此同时各线程等待,此时各线程是被阻塞住的),从缓存中取出日志信息,获得输出流进行输出,将缓存解锁(各线程收到提醒,可以接着写日志了)
众所周知,磁盘IO操作、网络IO操作、JDBC操作等都是非常耗时的,日志输出的主要性能瓶颈也就是在写文件、写网络、写JDBC的时候。日志是肯定要记的,而要采用异步方式记,也就只有将这些耗时操作从主线程当中分离出去才能真正的实现性能提升,也只有在线程间同步开销小于耗时操作时使用异步方式才真正有效!现在我们接着分别来看看这几种记录日志的方式。
将日志记录到本地文件
同样都是写本地文件Log4j本身有一个buffer处理入库,采用异步方式并不一定能提高性能(主要是如何配置好缓存大小);而线程间的同步开销则是非常大的!因此在使用本地文件记录日志时不建议使用异步方式。
将日志记录到JMS
JMS本身是支持异步消息的,如果不考虑JMS消息创建的开销,也不建议使用异步方式。
将日子记录到SOCKET
将日志通过Socket发送,纯网络IO操作不需要反馈,因此也不会耗时
将日志记录到数据库
众所周知JDBC是几种方式中最耗时的:网络、磁盘、数据库事务,都使JDBC操作异常的耗时,在这里采用异步方式入库倒是一个不错的选择。
将日志记录到SMTP
同JDBC
性能测试
在同步和异步方式下,同时起1000个线程,分别测试记录到文件和数据库中的时间消耗,每类测试连测5遍避免误差。
测试环境
1、WINDOWS XP SP2、JDK 1.5、ORACLE 9i2(本地)、log4j-1.2.14.jar
2、MutiTest.java用来测试同步方式,读取配置文件:log4j.properties
MutiTestAsyncAppender.java用来测试异步方式,读取配置文件:log4j.xml
3、每次测试先删除日志文件或清空表,确保测试独立性
测试结果如下:
FileAppender |
|
|
|
同步方式 |
最晚线程执行时间 |
最早线程执行时间 |
消耗时间 |
|
1 |
1.23209E+12 |
1.23209E+12 |
156 |
|
2 |
1.23209E+12 |
1.23209E+12 |
172 |
|
3 |
1.23209E+12 |
1.23209E+12 |
172 |
|
4 |
1.23209E+12 |
1.23209E+12 |
188 |
|
5 |
1.23209E+12 |
1.23209E+12 |
157 |
|
|
|
|
|
|
异步方式 |
最晚线程执行时间 |
最早线程执行时间 |
消耗时间 |
|
1 |
1.23209E+12 |
1.23209E+12 |
157 |
|
2 |
1.23209E+12 |
1.23209E+12 |
188 |
|
3 |
1.23209E+12 |
1.23209E+12 |
156 |
|
4 |
1.23209E+12 |
1.23209E+12 |
187 |
|
5 |
1.23209E+12 |
1.23209E+12 |
172 |
|
|
|
|
|
|
JDBCAppender |
|
|
|
同步方式 |
最晚线程执行时间 |
最早线程执行时间 |
消耗时间 |
|
1 |
1.23209E+12 |
1.23209E+12 |
281 |
|
2 |
1.23209E+12 |
1.23209E+12 |
172 |
|
3 |
1.23209E+12 |
1.23209E+12 |
172 |
|
4 |
1.2321E+12 |
1.2321E+12 |
171 |
|
5 |
1.2321E+12 |
1.2321E+12 |
203 |
|
|
|
|
|
|
异步方式 |
最晚线程执行时间 |
最早线程执行时间 |
消耗时间 |
|
1 |
1.2321E+12 |
1.2321E+12 |
94 |
|
2 |
1.2321E+12 |
1.2321E+12 |
94 |
|
3 |
1.2321E+12 |
1.2321E+12 |
94 |
|
4 |
1.2321E+12 |
1.2321E+12 |
94 |
|
5 |
1.2321E+12 |
1.2321E+12 |
125 |
|
结论
由以上测试结果可以得出异步方式记录日志并不是什么情况下都能提升性能的,相反由于线程间的同步开销,甚至可能降低性能;只有像在JDBC操作或是SMTP之类的记录耗时比较长的情况下,使用异步入库方式才是个好选择。
PS:第一次写这么长的文章,欢迎大家指摘。
分享到:
相关推荐
"(转)Log4j的AsyncAppender能否提升性能"这个标题涉及到Log4j的一个特性——AsyncAppender,它是Log4j为了提高日志处理性能而引入的一种异步日志写入机制。 AsyncAppender的主要工作原理是通过使用单独的线程池来...
《深入理解Log4j2 Demo性能测试:探索异步日志的魅力》 在软件开发过程中,日志记录是一项至关重要的任务,它可以帮助开发者追踪程序运行状态、定位问题以及进行性能优化。Log4j2作为Java领域广泛使用的日志框架,...
此外,Log4j2的AsyncAppender利用了LMAX Disruptor库,这是一个高性能的线程间通信库,能进一步降低同步开销。 总的来说,Log4j2的异步日志功能对于需要高性能日志记录的系统来说是一个强大的工具。通过源码测试和...
**日志框架Log4j详解** 在Java编程中,日志记录是不可...理解和熟练使用Log4j,对于提升Java应用的调试和维护效率有着重要作用。在实际项目中,根据需求选择合适的配置和使用方式,可以使日志记录更加高效和有针对性。
《深入理解Log4j:Java项目中的日志神器》 ...正确理解和使用log4j-1.2.16.jar,不仅可以提升开发效率,还能为项目的稳定性和维护性提供有力保障。通过不断学习和实践,开发者可以更有效地利用Log4j来解决实际问题。
《深入理解Spring Boot Starter Log4j2》 在Java开发领域,日志系统扮演着至关重要的角色,它帮助开发者记录程序运行过程中...在实际开发中,掌握Log4j2的配置和使用,能帮助我们更好地追踪问题,提升项目的可维护性。
Log4j2引入了异步日志记录器,通过使用后台线程处理日志事件,从而避免了这种阻塞,极大地提升了应用的性能。 **多线程支持** 在多线程环境中,Log4j2能够确保日志事件的正确性和顺序。每个线程都有自己的日志上...
Apache Log4j是Java平台上的一个著名日志记录框架,其2.0版本的重大更新带来了许多性能提升和功能增强。Log4j 2.0 RC1(Release Candidate 1)是该系列的一个候选版本,意味着它在正式发布之前用于测试和反馈。这个...
为了提高性能,log4j-1.2.17引入了异步日志记录,通过使用`AsyncAppender`,可以在不影响主线程性能的情况下,将日志输出任务放到后台处理。此外,合理配置日志级别,避免不必要的日志输出,也能显著提升系统效率。 ...
4. **自定义Layout**:如果内置的Layout不能满足需求,可以编写自定义的Layout类。 综上所述,Log4j与Spring的整合使得日志管理更加便捷,同时,Log4j丰富的配置选项和强大的功能使其成为Java日志处理的首选工具。...
Log4j 2.23.0是其最新的稳定版本,包含了对性能、安全性和稳定性的提升。下面我们将详细探讨Log4j 2的核心特点、主要组件以及如何在Java项目中使用它。 1. **核心特点** - **性能优化**:Log4j 2采用了异步日志...
8. **性能优化**:Log4j 2.10.0对性能进行了进一步优化,例如减少了内存分配和对象创建,提升了日志写入速度。源码分析可以帮助我们理解这些优化措施。 9. **兼容性与迁移**:尽管Log4j 2带来了许多新特性,但同时...
四、Log4j的高级特性 1. 自定义Appender和Layout:Log4j允许开发自定义的Appender和Layout,以满足特殊需求,如发送日志邮件、写入特殊格式的文件等。 2. 异步日志:通过AsyncAppender,可以实现日志输出的异步化...
Log4Qt是Qt框架下的一款日志记录库,它基于流行的Java日志库log4j设计,为C++开发者提供了一套强大、灵活的日志处理机制。本文将深入探讨Log4Qt日志管理的核心概念、功能特性以及如何在实际项目中有效应用。 一、...
- **性能提升**:Log4j 2.x 引入了新的日志实现,提供更高的性能和更低的内存占用。 - **AsyncAppender**:异步记录日志,提高应用性能。 - **JSON 和 XML 输出**:支持结构化的日志输出,方便数据分析。 通过本...
通过深入理解并实践Log4j中文版API,开发者能够更好地管理和利用日志信息,提升开发效率,同时确保应用程序的稳定性和可维护性。在实际项目中,合理的日志记录策略对于问题的定位和排查至关重要,而Log4j正是实现这...
Log4j是一款广泛应用于Java平台的日志记录框架,它的核心功能是...理解并熟练运用Log4j的配置和API,对于提升开发效率和维护质量至关重要。本资料中的jar包和配置文件,正是为了方便用户在项目中快速集成和使用Log4j。
例如,Log4j 2支持更丰富的插件体系、异步日志处理和动态日志配置,SLF4J则是一个日志抽象层,允许开发者在不修改代码的情况下切换不同的日志实现。 总结,Log4j 1.2.14作为经典的日志框架,其易用性和灵活性在Java...
理解并掌握Log4j的使用,对于提升Java应用的调试效率和维护性至关重要。通过合理配置log4j.properties,我们可以定制符合项目需求的日志系统,使得问题排查变得更加便捷。同时,SLF4J的引入为日志框架的选择提供了更...