Log4Net 性能
我编写了一个 C# 应用程序,该应用程序在循环中不断运行,并且多个线程写入 log4net 文件。
问题是应用程序运行的时间越长,完成循环所需的时间就越多。我运行了 ANTS 性能分析器,并注意到大部分 CPU 时间都花在了使用 log4.net 进行日志记录上。
日志越详细,使用的 CPU 就越多,30 分钟后,CPU 使用率达到 100%。如果我禁用记录,循环所花费的时间将随着时间的推移保持不变。我查看了 Windows 性能监视器,发现物理磁盘大部分时间处于空闲状态。
我试图将日志记录保持在最低限度,但即使日志记录量相对较少,我仍然遇到这个问题。
以下是我的 Log4net.xml 配置文件的示例:
<log4net>
<root>
<!-- Levels: OFF, DEBUG, INFO, WARN, ERROR, FATAL-->
<level value="INFO" />
<appender-ref ref="RollingLogFileAppender" />
</root>
<!--Logs to a file-->
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="c:\\logs\\log-file.txt" />
<appendToFile value="true" />
<lockingModel type="log4net.Appender.FileAppender+ExclusiveLock" />
<rollingStyle value="Composite" />
<datePattern value="yyyyMMdd" />
<maxSizeRollBackups value="20" />
<maximumFileSize value="1MB" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger %L %M Schdl:[%property{scheduleContext}] Job:[%property{jobContext}] - %message%newline" />
</layout>
</appender>
</log4net>
我在每个记录对象中使用相同的记录器。
log4net.ILog logger;
log4net.Config.BasicConfigurator.Configure();
logger = log4net.LogManager.GetLogger(typeof(myProject));
为什么它运行的时间越长,使用的CPU就越多?
任何有关如何改进这一点的建议将不胜感激。
I have written a C# app that runs constantly in a loop and several threads write to a log4net file.
The issue is that the longer the app is running, the more time it takes to complete a loop. I have run a ANTS Performance profiler, and noticed that most of this CPU time is spent logging with log4.net.
The more verbose the logs the more CPU it uses and after 30 minutes it's using 100% of the CPU. If I disable logging the time taken for a loop remains constant over time. I had a look at Windows Performance Monitor and the Physical Disk is most of the time IDLE.
I have tried to keep my logging to a minimum, but even with relatively low amounts of logging im still experiencing the issue.
Here is a sample of my Log4net.xml configuration file:
<log4net>
<root>
<!-- Levels: OFF, DEBUG, INFO, WARN, ERROR, FATAL-->
<level value="INFO" />
<appender-ref ref="RollingLogFileAppender" />
</root>
<!--Logs to a file-->
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="c:\\logs\\log-file.txt" />
<appendToFile value="true" />
<lockingModel type="log4net.Appender.FileAppender+ExclusiveLock" />
<rollingStyle value="Composite" />
<datePattern value="yyyyMMdd" />
<maxSizeRollBackups value="20" />
<maximumFileSize value="1MB" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger %L %M Schdl:[%property{scheduleContext}] Job:[%property{jobContext}] - %message%newline" />
</layout>
</appender>
</log4net>
I am using the same logger from every object that logs.
log4net.ILog logger;
log4net.Config.BasicConfigurator.Configure();
logger = log4net.LogManager.GetLogger(typeof(myProject));
Why would it use more and more CPU the longer it runs?
Any advise on how to improve this would be appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您是否在每个记录对象中配置 log4net?从你的代码来看是这样的。配置应该每个进程完成一次,例如在启动时,然后您的对象应该只需要获取记录器。
对于每个需要记录的类,我通常具有以下模式:
使用此模式,您将自动获取根据类的名称空间和名称分层的记录器。
Are you configuring log4net in every object that logs? It looks like that from your code. Configuration should be done once per process, e.g. at startup and then your objects should only have to acquire the logger.
For each class that needs to log I usually have the following pattern:
Using this pattern you will automatically get loggers that are hierarchical according to the namespace and name of the class.
你用这些上下文属性做什么?
Schdl:[%property{scheduleContext}] Job:[%property{jobContext}]
如果您在此处分配的不仅仅是一个值(或具有简单 ToString() 方法的对象),它还可以性能陷入困境。请参阅活动属性值下的 log4net 手册,了解以下内容:我在说什么。Peter Lillevold 有一个关于仅配置 log4net 一次的好建议。您还可以将以下行放入 AssemblyInfo.cs 文件中:
以下行很容易剪切并粘贴到任何执行日志记录的类中:
您还可以尝试打开 log4net 内部日志记录以查看发生了什么:
What are you doing with those Context Properties?
Schdl:[%property{scheduleContext}] Job:[%property{jobContext}]
If you assign something more than just a value here (or an object with a simple ToString() method), it can bog down performance. See the log4net manual under Active Property Values for an idea of what I'm talking about.Peter Lillevold has a good suggestion about configuring log4net only once. You can also put the following line in your AssemblyInfo.cs file:
The following line is easy to cut and paste into any class that does logging:
You also might try turning on log4net internal logging to see what's going on:
(我以前从未使用过 log4net,因此请谨慎使用我推荐的内容)
您可以为 log4Net 组件编写一个异步代理并登录专用线程。您将不再尝试写入日志文件而阻塞主线程。
如果 log4net 已经有异步代理,那么这一切都是无用的。
(I have never used log4net before so take what I recommend with caution)
You could write an async proxy to log4Net component and log on a dedicated thread. You will no longer be blocking your main threads with attempts to write to the logfile.
This is all useless if log4net already has an async proxy.