BufferingForwardingAppender in log4net
https://blog.csdn.net/szx1999/article/details/50073857
7. 写日志会影响系统性能吗?
写日志必然是会消耗一定资源的,而RollingFileAppender也不是线程安全的。为了减小log4net影响系统性能的嫌疑,我们加入lockingModel参数,使用FileAppender.MinimalLock来减少并发时发生死锁的概率:
<param name="lockingModel" type="log4net.Appender.FileAppender+MinimalLock" />
尽管如此,文件的I/O始终是耗性能的,有没有办法缓存一批日志,然后一次性写入文件呢?BufferingForwardingAppender正是为此而生,我们下章再介绍如何使用它。
https://stackoverflow.com/questions/11319319/log4net-bufferingforwardingappender-performance-issue
I found out the issue.
The BufferingForwardingAppender
is inheriting from BufferingAppenderSkeleton
(as are other appenders making use of logging events buffering such as AdoNetAppender
, RemotingAppender
, SmtpAppender
..).
The BufferingAppenderSkeleton
is actually buffering logging events before actually delivering them to the target appender once a certain condition is met (buffer full for example).
According to documentation of the LoggingEvent
class (representing a logging event, and containing all values (message, threadid ...) of the event) :
Some logging events properties are considered "volatile", that is the values are correct at the time the event is delivered to appenders, but will not be consistent at any time afterwards. If an event is to be stored and the processed at a later time, these volatile values must be fixed bycalling FixVolatileData. There is a performance penalty incurred by calling FixVolatileData but is is essential to maintain data consistency
These "volatile" properties are represented by the FixFlags
enumeration containing flags such as Message, ThreadName, UserName, Identity ... so all volatile properties. It also contains the flag "None" (fix no properties), "All" (fix all properties) and "Partial" (fix only a certain predefine dset of properties).
Whem the BufferingAppenderSkeleton
is instanciated, by DEFAULT it sets the fixing to "All" meaning that all "volatile" properties should be fixed.
In that context, for each LoggingEvent appended into the BufferingAppenderSkeleton, ALL "volatile" properties will be fixed before the event is inserted in the buffer. This includes the properties Identity (username) and LocationInformation (stack trace) even if these properties are not included in the layout (but I guess it makes some kind of sense if the layout is changed to include these properties at a later time while a buffer has been already been filled with LoggingEvents).
However in my case this really HURTS performance. I am not including the Identity and LocationInformation in my layout and don't plan to (mainly for performance issues)
Now for the solution ...
There are two properties in BufferingAppenderSkeleton
which can be used to control the FixFlags
flag value of the BufferingAppenderSkeleton
(once again by default it is set to "ALL" which is not very nice !). These two properties are Fix
(FixFlags type) and OnlyFixPartialEventData
(bool type).
For a fine tune of the flag value or to disable all fix, the Fix
property should be used. For a specific partial predefined combination of flags (not including Identity or LocationInfo), the OnlyFixPartialEventData
can be used instead by setting it to "true".
If I reuse the configuration sample above (in my question), the only change made to the configuration to unleash performance is indicated below:
<appender name="BufferingForwardingAppender" type="log4net.Appender.BufferingForwardingAppender">
<bufferSize value="512" />
<appender-ref ref="RollingLogFileAppender" />
<Fix value="0"/> <!-- Set Fix flag to NONE -->
</appender>
Using this modified configuration, the benchmark code execution presented in my question above, is dropping from approx 14000ms to 230ms (60X faster) ! And if I use <OnlyFixPartialEventData value="true"/>
instead of disabling all fix it is taking approx 350ms.
Sadly, this flag is not very well documented (except in the SDK documentation, a little bit) .. so I had to dig deep into log4net sources to find the issue.
This is particularly problematic especially in the "reference" configuration samples, this flag appears nowhere (http://logging.apache.org/log4net/release/config-examples.html). So the samples provided for BufferingForwardingAppender, and AdoNetAppender (and other appenders inheriting from BufferingAppenderSkeleton) will give TERRIBLE performance to users, even if the layout they are using is pretty minimal.
https://www.cnblogs.com/wigis/p/5023229.html
http://www.nimaara.com/2016/01/01/high-performance-logging-log4net/
https://github.com/NimaAra/Easy.Logger
Problems with BufferingForwardingAppender
The BufferingForwardingAppender
only flushes its events once the bufferSize
is full unless you specify lossy
to be true
so this means if you have an application producing a single log event every 1 second you would have to wait 512 seconds for the batch to be flushed out. This may not be a problem for you and if it is not then I highly recommend using this forwarder as it has great GC and CPU performance but if you need real-time monitoring of every log entry and a higher throughput then continue reading.
Another point we should be aware of is that this forwarder is not asynchronous it merely batches the events so the application thread(s) producing the log events will be blocked while the buffer is being flushed out.
The solution
Having considered the points above, I thought I could do better so say hello to my little friend AsyncBufferingForwardingAppender
.
This buffering forwarder uses a worker thread which batches up and flushes the log events in the background, it also detects if it has been idle meaning if there has not been enough log events to cause the buffer to be flushed it will invoke a manual flush which addresses the problem I mentioned above and since it is developed as a forwarder you can add additional appenders to it for example it can forward the log events to the Console
, DB
or any other appender that you might have all at the same time.
BufferingForwardingAppender in log4net的更多相关文章
- log4net的各种Appender配置示例
Apache log4net™ Config Examples Overview This document presents example configurations for the built ...
- Log4net 日志使用介绍
概述 Log4net 有三个主要组件:loggers,appenders 和 layouts.这三个组件一起工作使得开发者能够根据信息类型和等级(Level)记录信息,以及在运行时控制信息的格式化和信 ...
- log4net学习笔记
一直想找一个好用的日子类,今天偶然的机会看到了log4net这个类库,过来学习一下. log4net是.NET框架下的一个日子类库,官网是http://logging.apache.org/log4n ...
- log4net日志组件
转载:http://www.cnblogs.com/knowledgesea/archive/2012/04/26/2471414.html 一.什么是log4net组件 Log4net是基于.net ...
- Apache log4net™ Config Examples
Overview This document presents example configurations for the built-in appenders. These configurati ...
- Log4net 日志
Log4net 日志使用介绍 概述 Log4net 有三个主要组件:loggers,appenders 和 layouts.这三个组件一起工作使得开发者能够根据信息类型和等级(Level)记录信息,以 ...
- log4net性能小探
初步测试了Log4性能.Appender架构如下. 一般客户端,使用FileAppender,把Log记录在本地磁盘. <lockingModel type="log4net.Appe ...
- Log4net_配置
Log4net 有三个主要组件:loggers,appenders 和 layouts.这三个组件一起工作使得开发者能够根据信息类型和等级(Level)记录信息,以及在运行时控制信息的格式化和信息的写 ...
- log4net使用手册
1. log4net简介 log4net是.Net下一个非常优秀的开源日志记录组件.log4net记录日志的功能非常强大.它可以将日志分不同的等级,以不同的格式,输出到不同的媒介.Java平台下,它还 ...
随机推荐
- EditText相关属性设置
1.默认不弹出软件盘 在AndroidManifest.xml设置: <activity android:name="com.demo.Activity" ...
- java 多种判断key是否在map中存在的方法
java 中有时候会遇到判断传过来的map里是否包含了指定的key,我目前只发现两种办法,如果有其他方法欢迎补充 我添加上去: HashMap map = new HashMap(); map.put ...
- 【转】C#操作word定位光标
十一.上下左右移动光标位 private void moveLeft() { object moveUnit = Microsoft.Office.Interop.Word.WdUnits.wdWor ...
- :eq()中的参数详解——需要注意
:eq()的括号中的参数如果是非负数则在DOM对象中按从上到下的顺序查找指定的元素,但是,如果是是负数,则在DOM中从下向上查找指定元素. 如下实例: 如果 $("#divTag div:e ...
- C#访问修饰符比较
- Machine Learning - week 2 - 编程练习
3. % J = COMPUTECOST(X, y, theta) computes the cost of using theta as the % parameter for linear r ...
- python并发编程&多线程(二)
前导理论知识见:python并发编程&多线程(一) 一 threading模块介绍 multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性 官网链 ...
- hbase中清空整张表的数据
hbase(main):005:0> truncate 'fr:test' Truncating 'FaceBase' table (it may take a while): - Disabl ...
- webview自动循环播放
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=&q ...
- boost之正确性和测试
BOOST_ASSERT在debug模式下有效. #include <iostream> #include <boost/assert.hpp> using namespace ...