Page 487 - 《软件学报》2024年第4期
P. 487
吴圣垚 等: HiLog: OpenHarmony 的高性能日志系统 2065
会占用系统的 CPU 资源, 侵占了其他系统服务的资源. 因此 libhilog 提供进程流控功能, libhilog 会统计本进程在
一定时间内的日志流量, 按照默认配额或者进程白名单设置的配额进行控制, 对超出配额的日志进行抛弃.
日志流量
抛弃 流量控制
libhilog hilogd libhilog
q
日志 hilog_buffer 日志
生成 生成
进程流控 业务流控 进程流控
socket_input socket_input socket_input
客户端 服务端 客户端
时间
t 0 +Δt t 0 +2Δt t 0 +3Δt
t 0
(a) 原理图 (b) 模型图
图 7 流量控制原理和标准 HiLog 的流量控制模型
实现业务流控可以有效管理多进程业务的日志流量, 并进一步减少 hilog_buffer 对系统资源的占用. 在
OpenHarmony 系统中可以通过领域标识 (Domain) 将进程进行归类, 具备相同 Domain 的进程被归纳为同一业务.
因此当某个多进程业务总的日志量过大时, 一方面会造成不同业务之间的日志资源不公平占用, 另一方面也会增
加 hilog_buffer 的覆盖写操作频率. 因此 hilogd 提供业务流控功能, 依据日志的 Domain 信息统计一定时间单业务
的日志写入量, 按照缺省配额或者系统开发者设置的配额进行控制, 如果超过相应配额则丢弃, 不写入 hilog_buffer.
轻量 HiLog 日志系统不设置 hilogd 模块, 因此仅具备 libhilog 提供的进程流控能力. 同时由于轻量设备的特性, 系
统不会运行大量的进程, 因此减少业务流控也是没有问题的.
3.3.5 HiLog 日志系统缓冲区管理
图 8 描绘了标准 HiLog 的缓冲区 hilog_buffer 的结构, 所有进程的日志都将写入用户态 hilog_buffer. 为了高
效利用碎片化的内存空间, hilog_buffer 采用链表作为数据结构. 同时, 将链表设计为双向循环结构, 这样可以有效
降低日志的排序、插入、读取等操作时指针需要跳转的链表节点数目, 提高性能. hilog_buffer 的特性如下.
0 1 2 3 4 5
r r 1 r 2 r 3 r 4 w
图 8 HiLog 用户态日志缓冲区 (hilog_buffer) 示意图
(1) 时间戳有序: hilog_buffer 中的数据按照日志数据的时间戳排序. 排序是日志系统中非常重要的功能, 因为
正确的时间顺序是提取正确逻辑的前提. 为了给开发和维护人员提供符合逻辑的信息, 日志在输出时需要具备正
确时序. 在 HiLog 中, 多进程需要通过 Socket 将日志数据传输到 hilog_buffer, 这一过程在 OpenHarmony 这种分时
操作系统中可能会存在随机的延时, 进而导致日志产生时间顺序与到达缓冲区的时间顺序不一致的问题. 如果不
进行排序, 在打印时时就会以错误的顺序输出, 造成使用者阅读困难甚至误解. 排序功能存在“先排序”和“后排序”
两种方案, “先排序”是指日志在写入日志缓冲区时进行排序; “后排序”是指从缓冲区读取日志进行输出时排序. 考
虑到 HiLog 缓冲区的单生产者、多消费者模型, 先排序方案更优. 原因在于: ① “先排序”方案执行一次排序即可
解决顺序问题, 由于缓冲区内日志有序, 排序是较为简单的, 只需将新到日志的时间戳依次与缓冲区日志的时间戳
进行比较 (由新到旧) 然后插入即可. ② “后排序”需要每个消费者都进行排序, 由于缓冲区内日志无序, 消费者需
要遍历一次链表才能排序一条日志, 效率较低.
(2) 读写指针: hilog_buffer 包含 3 类读写指针成员. 如图 8 所示, 3 类指针成员分别为: 写指针 w, 指向当前