写了个轻量级 logging lib, 在高并发下比 logrus, seelog 等常用的库效率更佳

2016-03-06 21:50:43 +08:00
 hjweddie

在工作中负责开发 qps 较高的中间件过程中,发现原来使用的 seelog 中每次函数调用均会调用 runtime.Caller 及 runtime.FuncForPC 这两个极为耗时的操作(单 goroutine 下,每次需要 0.1~0.2ms),这意味着调用 n 次 seelog 的日志函数后,耗时将增加 n * (0.1~0.2)ms. 换用了 logrus 后情况有所缓解,而且也挺好用的(JSON 格式输出)。但是 logrus 不支持配置文件,这一点上没有 seelog 可以通过 xml 文件配置来的优雅。此时在想,有没两者优点合二为一的呢?

另外,在 fmt 包格式化字符串的探索中,发现将格式化字符串和输出过程融合,而不等整个字符串格式化完再输出(一边格式化,一边输出),这样的效率会提高 20%左右,在亲测在 100 goroutines 的情况下提高更为可观。由此便有了这个库的初步构想。最后增加了 buf.io, timeCache, format const, bytes.buffer 等各种技巧的使用,使得日志输出效率极大的提高。最终用到线上环境中,运行稳定,中间件的处理能力也得到了满意的提升。

期待感兴趣的大大们的建议~

项目地址:
https://github.com/YoungPioneers/blog4go

Introduction

BLog4go is an efficient logging library written in the Go programming language, providing logging hook, log rotate, filtering and formatting log message.

BLog4go 是高性能日志库。创新地使用“边解析边输出”方法进行日志输出,同时支持回调函数、日志淘汰和配置文件。可以解决高并发,调用日志函数频繁的情境下,日志库造成的性能问题。



Features

Benchmark

I do some benchmark on a HDD disk comparing amoung fmt,blog4go,seelog,logrus. Benchmark Code

BenchmarkBlog4goSingleGoroutine-4                    1000000          1087 ns/op
BenchmarkBlog4goMultiGoroutine-4                       30000         56569 ns/op
BenchmarkFmtFormatSingleGoroutine-4                   300000          5104 ns/op
BenchmarkFmtFormatWithTimecacheSingleGoroutine-4      300000          4256 ns/op
BenchmarkFmtFormatWithTimecacheMultiGoroutine-4         3000        509579 ns/op
BenchmarkLogrusSingleGoroutine-4                      100000         13757 ns/op
BenchmarkLogrusWithTimecacheSingleGoroutine-4         100000         12752 ns/op
BenchmarkLogrusWithTimecacheMultiGoroutine-4            1000       2049809 ns/op
BenchmarkSeelogSingleGoroutine-4                       50000         32846 ns/op
BenchmarkSeelogMultiGoroutine-4                         1000       3191334 ns/op

It shows that blog4go can write log very fast, especially in situation with multi goroutines running at the same time~

8177 次点击
所在节点    分享创造
9 条回复
zhengji
2016-03-06 22:05:49 +08:00
给作者赞一个
zzn
2016-03-06 22:35:20 +08:00
边解析边输出?什么鬼?
hjweddie
2016-03-06 22:47:12 +08:00
@zzn 就是格式化字符串的过程中,省略了字符串拼接的步骤,解析成功一部分就马上输出到对应的地方(bufio, console 等)
Unknwon
2016-03-07 02:32:38 +08:00
用 XML 配置表示有点蛋疼。。。
hjweddie
2016-03-07 09:35:08 +08:00
@Unknwon 嗯嗯,我本身也比较喜欢相对简洁的 yaml 。在编写代码的时候,持着尽量不依赖非官方库的原则,没有引用非官方的 yaml 的包。不知道可否介绍下 xml 外的实现方法呢? 另外我自己试过使用 json 格式的,配置文件写起来也觉得挺麻烦
Unknwon
2016-03-07 14:38:15 +08:00
@hjweddie 我看了一下你的示例配置。。我感觉用 INI 更简洁。。

https://github.com/go-ini/ini 这个包还提供像 JSON, XML 那样直接映射到结构体的功能,你可以试试。(其实是个软广)
hjweddie
2016-03-07 17:01:34 +08:00
@Unknwon 谢谢你的建议,我会考虑下 ini,json,yaml 相关的配置方法
kulle
2016-04-26 18:20:13 +08:00
err := log.NewWriterFromConfigAsFile("blog4go_config.xml")
defer log.Close()
请问,如果我的程序用到 blog4go ,写一个全局变量存放这个 log ,是不是不需要关闭?
hjweddie
2016-07-17 21:59:25 +08:00
@kulle 需要调用 Close 方法来关闭的噢~

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/261539

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX