ZLogger 高性能日志库

github源码:https://github.com/Cysharp/ZLogger/tree/master

作者两篇文章1(部分旧的不适用):https://neuecc.medium.com/zlogger-zero-allocation-logger-for-net-core-and-unity-d51e675fca76

作者两篇文章2:https://neuecc.medium.com/zlogger-v2-architecture-leveraging-net-8-to-maximize-performance-2d9733b43789

C#10 自定义内插字符串:https://devblogs.microsoft.com/dotnet/string-interpolation-in-c-10-and-net-6/

C# 源代码生成器简介:https://devblogs.microsoft.com/dotnet/introducing-c-source-generators/


概述

  • 高性能;支持模板配置;可以动态生成日志代码的日志库。

  • 可以解决常见unity日志问题:

    • 根据级别开关日志。

    • 字符串参数装箱问题。

    • 日志屏蔽不全的参数导致没必要的调用。

    • 线程异步的日志。

  • 可扩展:输出多个文件,自动生成额外参数。


和传统对比

日志开关统一

  • 平常开发打log没有统一日志库时,需要自己定义开关,通常也会漏开关,不受控。要么加宏开关,要么自己定义变量。
// 使用宏,需要代码头部定义宏,或者工程配置宏。
// 不用时,没有性能消耗,因为代码不会编译进去。就是不方便统一管理。
[Conditional("DEBUG_LOG")]
public static void DebugLog1(string str)
{
    Debug.Log($"DebugLog: {str}");
}
// 编译时,如果宏没开启,这行直接不会编译。
DebugLog1($"hello {id}");

// 自定义开关,开关可以统一。
// 不用时,还是会编译,如果参数会执行,有额外不必要开销。
// 在外面调用if判断也行,但得在所有打印日志前加if,大概率会漏。
public static void DebugLog2(string str)
{
    if (enable)
    {
         Debug.Log($"DebugLog: {str}");
    }
}
// 无论是否enable,这里都已经进行了字符串拼接了
DebugLog2($"hello2 {id}");
  • ZLogger加了一层日志包装,每个日志管理可以各自控制开关。
using var loggerFactory = LoggerFactory.Create(logging =>
{        
    // 设置输出日志的等级
    logging.SetMinimumLevel(LogLevel.Warning);
});

// 普通Log不会执行,包括参数,在编译时会调整
logger.Log(LogLevel.Information, $"Log {id}");

字符串装箱问题

  • 传统日志没有特殊处理,就是String.Format处理字符串,然后传给Debug.Log方法。
    在这里插入图片描述

  • ZLogger,通过C#的自定义内插字符串(InterpolatedStringHandler),实现对特殊参数用泛型代替,避免装箱操作。源码在:ZLoggerInterpolatedStringHandler.cs
    在这里插入图片描述

实现原理

在这里插入图片描述

1、2:初始化日志信息,字符串信息,判断是否开启

在这里插入图片描述

3:从池子里取或创建字符串模板

  • $"ZLog Hello {name} your id is {id}" 的模板:

  • ["ZLog Hello ", null, " your id is ", null]
    在这里插入图片描述

4:记录上下文,方法名,文件行号等

5:输出字符串

在这里插入图片描述
在这里插入图片描述

MagicalBox

  • MagicalBox:用来避免装箱,装任意数据
    在这里插入图片描述

编译时自动生成格式化日志代码

  • 需要编译c#版本preview版本(csc.rsp文件),LangVersion.props 改版本 11

  • 比起上面的日志生成,这个更高效,但需要额外写代码,也不保证调试正常,毕竟unity没直接支持。

  • ZLoggerMessage:https://github.com/Cysharp/ZLogger/tree/master?tab=readme-ov-file#zloggermessage-source-generator

  • 类似.net支持的: https://learn.microsoft.com/en-us/dotnet/core/extensions/logger-message-generator

  • https://devblogs.microsoft.com/dotnet/introducing-c-source-generators/

在这里插入图片描述


System.Span<T>

  • 常用于直接取数组的一段数据,直接取得相同地址数据,不会额外分配内存。比如可以代替String.SubString()的功能,且不生成新的字符串。

    • 比如将 “DateTime.Now:@date:yyyy-MM-dd”,分前后两段

    在这里插入图片描述

  • 也可以用于说明数组只读性,System.ReadOnlySpan<T>

    在这里插入图片描述

  • 操作一些编码

byte[] buffer = new byte[1024]; 
Span<byte> header = buffer.AsSpan(0, 128); // 取前128字节 
Span<byte> body = buffer.AsSpan(128);    
  • 分配临时栈内存
Span<int> stackData = stackalloc int[10]; // 栈上分配
for (int i = 0; i < stackData.Length; i++)     
{         
    stackData[i] = i;     
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值