You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NLog导致类变量访问速度骤降?原因及是否为预期行为?

这个800倍性能差的原因分析

哇,这个性能差异确实夸张,我来帮你拆解一下——这绝对不是NLog导致类变量访问本身变慢,而是初始化时机的锅,加上早期版本的适配开销被误测了!

1. 静态Logger的初始化时机踩了陷阱

你把_logger定义成static readonly,它的初始化是在类第一次被访问时触发的(也就是.NET的静态构造函数阶段)。当你第一次访问s1的时候,刚好触发了LogManager.GetCurrentClassLogger()的执行——而这个方法在NLog 4.5.3里可不是简单的new一个对象:

  • 它会加载NLog的配置文件(不管是nlog.config还是appsettings.json里的配置)
  • 通过反射获取当前类的完整类型信息,用来命名Logger实例
  • 初始化NLog的内部日志管理器、注册Logger实例
  • 还可能提前初始化日志目标(比如文件输出、控制台输出)

这些都是一次性的初始化开销,但如果你的性能测试刚好把第一次访问s1的时间算进去,那整个初始化的耗时都会被算到s1的访问时间里,看起来就像是变量访问慢了800倍——实际上是你把NLog的启动开销误当成了变量访问的开销。

2. 早期NLog与.NET Core 2的适配开销

.NET Core 2是比较早期的跨平台版本,NLog 4.5.3虽然支持它,但在配置加载和类型解析上的实现不如后续版本优化。比如早期的NLog在.NET Core下读取配置需要处理更多兼容性逻辑,反射操作的开销也比.NET Framework下更明显,这进一步放大了初始化的耗时。

3. 如何验证并解决这个问题

你可以用这几个方法验证我的猜测:

  • 提前初始化Logger:在性能测试代码的最开头,先手动调用一次LogManager.GetCurrentClassLogger(),然后再测s1和s2的速度,你会发现两者的差异又回到正常的2倍左右。
  • 显式静态构造函数:把Logger的初始化放到显式的静态构造函数里,提前完成初始化:
    class Program
    {
        private static readonly Logger _logger;
    
        // 显式静态构造函数,提前初始化Logger
        static Program()
        {
            _logger = LogManager.GetCurrentClassLogger();
        }
    
        // 你的其他类变量和测试代码...
    }
    
  • 用性能探查器定位:用Visual Studio的性能探查器跑一遍,你会发现耗时几乎全在NLog的初始化方法里,而不是类变量的访问操作上。

结论

这个现象不属于NLog的预期行为,只是因为静态Logger的初始化时机和测试逻辑重叠,加上早期版本的适配开销,导致了看起来夸张的性能差异。只要把Logger的初始化提前到测试开始前,这个问题就会消失。

内容的提问来源于stack exchange,提问作者Joe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:06:21