在工作中负责开发 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
BLog4go is an efficient logging library written in the Go programming language, providing logging hook, log rotate, filtering and formatting log message.
BLog4go 是高性能日志库。创新地使用“边解析边输出”方法进行日志输出,同时支持回调函数、日志淘汰和配置文件。可以解决高并发,调用日志函数频繁的情境下,日志库造成的性能问题。
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~
1
zhengji 2016-03-06 22:05:49 +08:00
给作者赞一个
|
2
zzn 2016-03-06 22:35:20 +08:00
边解析边输出?什么鬼?
|
3
hjweddie OP @zzn 就是格式化字符串的过程中,省略了字符串拼接的步骤,解析成功一部分就马上输出到对应的地方(bufio, console 等)
|
4
Unknwon 2016-03-07 02:32:38 +08:00
用 XML 配置表示有点蛋疼。。。
|
5
hjweddie OP @Unknwon 嗯嗯,我本身也比较喜欢相对简洁的 yaml 。在编写代码的时候,持着尽量不依赖非官方库的原则,没有引用非官方的 yaml 的包。不知道可否介绍下 xml 外的实现方法呢? 另外我自己试过使用 json 格式的,配置文件写起来也觉得挺麻烦
|
6
Unknwon 2016-03-07 14:38:15 +08:00
@hjweddie 我看了一下你的示例配置。。我感觉用 INI 更简洁。。
https://github.com/go-ini/ini 这个包还提供像 JSON, XML 那样直接映射到结构体的功能,你可以试试。(其实是个软广) |
8
kulle 2016-04-26 18:20:13 +08:00 via Android
err := log.NewWriterFromConfigAsFile("blog4go_config.xml")
defer log.Close() 请问,如果我的程序用到 blog4go ,写一个全局变量存放这个 log ,是不是不需要关闭? |