Log4j2的性能为什么这么好?
原创:詹嵩 某公司架构部中间件架构师
校对:程超 某公司架构部中间件负责人
一、logback和log4j2压测比较
1、logback压测数据
logback压测数据,50个线程,500万条日志写入时间。
logback:messageSize = 5000000,threadSize = 50,costTime = 27383ms logback:messageSize = 5000000,threadSize = 50,costTime = 26391ms logback:messageSize = 5000000,threadSize = 50,costTime = 25373ms logback:messageSize = 5000000,threadSize = 50,costTime = 25636ms logback:messageSize = 5000000,threadSize = 50,costTime = 25525ms logback:messageSize = 5000000,threadSize = 50,costTime = 25775ms logback:messageSize = 5000000,threadSize = 50,costTime = 27056ms logback:messageSize = 5000000,threadSize = 50,costTime = 25741ms logback:messageSize = 5000000,threadSize = 50,costTime = 25707ms logback:messageSize = 5000000,threadSize = 50,costTime = 25619ms
说明:
这个是logback日志的压测数据,在开发机(双核四线程),高配开发机(四核八线程)和服务器(32核)压测的效率都差不多,而且线程开多的时候,性能反而有下降,压测数据如下:
logback:messageSize = 5000000,threadSize = 100,costTime = 33376ms
这个是在32核机器上压测的平均值,高于开发机。
2、log4j2压测数据
log4j2压测数据,因测试数据会占用一些篇幅,这里仅取中位数,但上下差距并不大
log4j2:messageSize = 5000000,threadSize = 100,costTime = 15509ms ---开发机 log4j2:messageSize = 5000000,threadSize = 100,costTime = 5042ms ---高配开发机 log4j2:messageSize = 5000000,threadSize = 100,costTime = 3832ms ---服务器
本次压测,基本上与log4j2官网数据吻合,经过验证异步日志确实可以极大的提高IO效率
下图为同步、异步、只异步appender的性能对比
和其他日志框架的对比:
从本次压测中,也得知确实在同步日志写到一定程度下,会大大的影响服务器的吞吐率,各位同学可以根据自己项目的情况,做日志上的优化。
下图为并发量大时,日志框架对系统吞吐率产生的影响,这里看logback和log4j确实影响很大,但实际情况中,感受到的要远远小于此图。
二、压测配置
log4j2的效率可以在多线程时,在线程数量大的情况下,超过logback10倍左右!500万数据大概0.25G,只需3秒左右就可以写进磁盘。
在配置上,首先第一条建议是如果做异步,那么所有的日志都是异步写,这样的性能指数的增长是量级的。当然也可以混合部署,但是性能影响就没有全部异步这么明显。
配置上,优化一定的属性,对性能也有一定的影响。
log4j2本身提供了20多种appender供使用者选用,但一般开发中采用的就是RollingRandomAccessFile,该组件有多个属性配置,常用的做一下说明(其他配置对性能意义不大,有兴趣的同学可自己去官网查看)
一般采用默认值,除非系统写日志的IO影响了主线程的运行,可以调大该配置。
本次压测采用的日志配置
在asyncRoot中可以添加includeLocation="true"属性,该属性如果为true,可以携带类名和行号等信息,但是抽取这些信息,会有一些性能损耗
log4j2改版以后,组件和功能极大丰富,有兴趣的同学可以去官网http://logging.apache.org/log4j/2.x/manual/index.html或找我来一起交流。
三、disruptor队列
查看底层代码,log4j2之所以能在异步写日志时性能提高这么多,离不开优秀的mq组件disruptor。
目前使用该队列的知名软件包括但不限于Apache Storm、Camel、Log4j 2。
由于时间有限,本篇着重讲解底层队列的实现,因为这个对性能的影响是最大的。
以此图为例:
同步性能最差,异步全局异步的性能接近异步appender的10倍,同样是异步实现的,为何性能有如此大的差距?
去看源码:
以上是异步Appender的实现,可以看到,内部内置了一个BlockingQueue队列,具体实现采用了ArrayBlockingQueue
接着是全局异步loggers的实现方式,可见内部的队列使用的是disruptor。
性能上的优劣,绝大部分原因都是数据模型的问题,往下我们分析一下BlockingQueue和disruptor的实现方式,由于篇幅有限,从JDK源码来看:
1、ArrayBlockingQueue
可以看到ArrayBlockingQueue采用的是加锁的方式来处理线程安全问题的。
加锁的问题,虽然历代JDK一直投入大量的精力去解决问题,比如优化Sync关键字的实现方式、添加读写锁等,但是由于结构特性的问题,一直无法从根本上解决性能开销问题。
题外话 _ 除了锁的问题,还牵涉到底层CPU在计算时读取内存数据的问题。
举个例子:当你遍历一个数组时(数组在CPU计算时,是简单数据结构),你读取到第一个元素时,其他元素也会相应的放入1级缓存(距离CPU最近),所以你遍历数据的方式是最快的,这就是简单数据结构的优势。
但是如果你在操作一个Queue时,一般会涉及几个变量,这里以ArrayBlockingQueue为例:
这里有三个变量,分别代表了下一个要出的元素下标,要进的元素下标和长度
当然,这几个简单类型是非常容易放入1级缓存并进行高速计算的,但是问题是,这个Queue是一个生产者和消费者的模型,牵涉到两端操作,于是当生产者写入元素时,takeIndex和putIndex数值发生改变,消费者在消费时要拿的takeIndex也跟着改变,这时就需要去主存中重新去取takeIndex,而无法利用1级缓存进行高速计算。
以上大致解释了ArrayBlockingQueue的性能劣势,接下来就看disputor如果解决这些问题。
2、Disputor
引入官网的一段话(首先要明白背景和诉求):
这里的表述和我们的目标一致,都是要解决锁和缓存缺失带来的性能开销问题。
引用几张官网的截图(风格还比较有趣):
https://www.slideshare.net/trishagee/introduction-to-the-disruptor?from=new_upload_email 这是该PPT的地址,有兴趣的同学可以关注下。
他们采用了环形数据结构来解决这个问题(他们称之为魔法圆环,或魔法圆圈之类的),此种数据结构的有点是,不需要记录额外的下标,直接由JNI返回可以操作的地址,然后当多线程并发读写的时候,使用的也是cas方式。
这样,不能使用1级缓存和加锁操作的问题就解决了(关于CAS大家可自行谷歌,有非常多的文章来介绍)。
由于篇幅和经历有限,本次分享先写到这里,如果之后对disruptor有需要的话,可以再次深入研究。
我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2o3frldj3qw44
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Mysql分库分表方案
Mysql分库分表方案 1.为什么要分表: 当一张表的数据达到几千万时,你查询一次所花的时间会变多,如果有联合查询的话,我想有可能会死在那儿了。分表的目的就在于此,减小数据库的负担,缩短查询时间。 mysql中有一种机制是表锁定和行锁定,是为了保证数据的完整性。表锁定表示你们都不能对这张表进行操作,必须等我对表操作完才行。行锁定也一样,别的sql必须等我对这条数据操作完了,才能对这条数据进行操作。 2.mysqlproxy:amoeba 做mysql集群,利用amoeba。 从上层的java程序来讲,不需要知道主服务器和从服务器的来源,即主从数据库服务器对于上层来讲是透明的。可以通过amoeba来配置。 3.大数据量并且访问频繁的表,将其分为若干个表。 比如对于某网站平台的数据库表-公司表,数据量很大,这种能预估出来的大数据量表,我们就事先分出个N个表,这个N是多少,根据实际情况而定。 某网站现在的数据量至多是5000万条,可以设计每张表容纳的数据量是500万条,也就是拆分成10张表。 那么如何判断某张表的数据是否容量已满呢?可以在程序段对于要新增数据的表,在插入前先做统计表记录数量...
- 下一篇
专访阿里视频云叔度:一场技术人的自我修行
从甘肃瓜州广显驿到新疆哈密小南湖佛寺,这段全长超过400KM的戈壁是唐代玄奘大师西行取经过程中最为凶险的路段。1300多年前,玄奘大师孤身一人,历经九死一生的重重挑战,最终成就了千古伟绩,受万世景仰。千年之后的2018年,“玄奘之路”BC连14位同伴在这段自我修行的路程中沿着大师昔日的足迹徒步前行,对极致的追求促使他们努力挑战生命的每个不可能。 其中,最让人感动的是一个打着点滴行进的身影,他在遭遇右腿受伤、电解质紊乱导致胃痉挛、能量耗尽等极限状况下仍坚持走完了最后的50公里。他就是阿里云的叔度,也是本文的采访主角。 打着点滴穿越戈壁的叔度 朱照远,花名叔度,阿里视频云总经理,现负责阿里云CDN、视频云、边缘计算等产品的业务和技术。他是开源Web服务器项目Tengine的发起人,研究方向包括高性能服务器开发、大型网站的架构和性能优化、云计
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- CentOS关闭SELinux安全模块
- CentOS7设置SWAP分区,小内存服务器的救世主
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Mario游戏-低调大师作品