一、性能基准测试
package test_golang_pool import ( "encoding/json" "fmt" "go.uber.org/zap" "go.uber.org/zap/zapcore" "os" "testing" ) type User struct { Name string `json:"name"` Age int `json:"age"` } // BenchmarkZapPrint func BenchmarkZapPrint(b *testing.B) { u := &User{Name: "jack", Age: 18} fmt.Println(u) b.ResetTimer() encode := zap.NewProductionEncoderConfig() encode.TimeKey = "" encode.LevelKey = "" encode.CallerKey = "" encode.MessageKey = "" ee := zapcore.NewJSONEncoder(encode) www := zapcore.NewCore(ee, os.Stdout, zap.InfoLevel) logger, _ := zap.NewProduction(zap.WrapCore(func(core zapcore.Core) zapcore.Core { return www })) defer logger.Sync() for i := 0; i < b.N; i++ { var f []zapcore.Field f = append(f, zap.Any("message", u)) logger.Info("success", f...) } } // BenchmarkSimplePrint func BenchmarkSimplePrint(b *testing.B) { u := &User{Name: "jack", Age: 18} b.ResetTimer() for i := 0; i < b.N; i++ { j, _ := json.Marshal(u) fmt.Println(string(j)) } }
二、测试结果
BenchmarkZapPrint-8 406218 2816 ns/op BenchmarkSimplePrint-8 492658 2441 ns/op
三、zap和logrus的性能比较
//goos: darwin //goarch: amd64 //pkg: test-pool //cpu: VirtualApple @ 2.50GHz //BenchmarkZap //BenchmarkZap-8 1685895 710.4 ns/op 128 B/op 1 allocs/op func BenchmarkZap(b *testing.B) { b.ReportAllocs() b.StopTimer() cfg := zap.NewProductionConfig() core := zapcore.NewCore( zapcore.NewJSONEncoder(cfg.EncoderConfig), zapcore.AddSync(io.Discard), zapcore.InfoLevel, ) logger := zap.New(core) b.StartTimer() for i := 0; i < b.N; i++ { logger.Info("success", zap.String("name", `jack`), zap.Int("age", 18), ) } } // goos: darwin // goarch: amd64 // pkg: test-pool // cpu: VirtualApple @ 2.50GHz // BenchmarkLogrus // BenchmarkLogrus-8 437836 2683 ns/op 1246 B/op 20 allocs/op // BenchmarkLogrus func BenchmarkLogrus(b *testing.B) { b.ReportAllocs() b.StopTimer() logger := logrus.New() logger.SetOutput(io.Discard) b.StartTimer() for i := 0; i < b.N; i++ { logger.WithFields(logrus.Fields{ "name": "jack", "age": 18, }).Info("success") } }
五、zap输出一行JSON到控制台
var once sync.Once type School struct { Name string `json:"name"` Age int `json:"age"` } // ZapLogger zap日志对象 var ZapLogger *zap.Logger func ZapPrintJson() { s := &School{ Name: "jack", Age: 18, } // 输出日志 f := BuildFiledList(s) GetZapLogger().Info("success", f...) } func GetZapLogger() *zap.Logger { once.Do(func() { cfg := zap.NewProductionConfig() cfg.EncoderConfig.TimeKey = "" cfg.EncoderConfig.LevelKey = "" cfg.EncoderConfig.CallerKey = "" cfg.EncoderConfig.MessageKey = "" core := zapcore.NewCore( zapcore.NewJSONEncoder(cfg.EncoderConfig), os.Stdout, zapcore.InfoLevel, ) ZapLogger = zap.New(core) }) return ZapLogger } func BuildFiledList(s *School) []zapcore.Field { var f []zapcore.Field f = append(f, zap.String("name", s.Name)) f = append(f, zap.Int("age", s.Age)) return f }
六、性能快的原因 ???
避免 interface{} 使用强类型设计 封装强类型,无反射 使用零分配内存的 JSON 编码器,尽可能避免序列化开销,它比其他结构化日志包快 4 - 10 倍 使用 sync.Pool 以避免记录消息时的内存分配 避免使用interface{}带来的开销(拆装箱、对象逃逸到堆上) 坚决不用反射,每个要输出的字段(field)在传入时都携带类型信息(这虽然降低了开发者使用zap的体验,但相对于其获得的性能提升,这点体验下降似乎也算不得什么) 使用sync.Pool减少堆内存分配(针对代表一条完整日志消息的zapcore.Entry),降低对GC压 logger 提供快速,分级,结构化的日志记录。所有的方法都是安全的,内存分配很重要,因此它的 API 有意偏向于性能和类型安全
七、零内存分配的JSON编码器,给各位演示一下大概的代码:
func GetJSONString() { b := buffer.Buffer{} // 下面会不断 switch zapField的类型给buff逐行添加数据拼接成json b.AppendByte('{') last := b.Len() - 1 if last < 0 { return } switch b.Bytes()[last] { case '{', '[', ':', ',', ' ': break default: b.AppendByte(',') } b.AppendByte('"') s := "name" b.AppendString(s) b.AppendByte('"') b.AppendByte(':') b.AppendBool(true) b.AppendByte('}') }
看一下官方包 json.Marshal 用了很多的反射 简单实现一个试试
type L struct { Name string `json:"name"` } func TestReflect(test *testing.T) { l := L{Name: "rose"} var t reflect.Type t = reflect.TypeOf(l) var v reflect.Value v = reflect.ValueOf(l) json := "{" for i := 0; i < t.NumField(); i++ { if t.Field(i).Tag.Get("json") != "-" { json += "\"" + t.Field(i).Tag.Get("json") + "\":\"" + v.FieldByName(t.Field(i).Name).String() + "\"" } } json += "}" fmt.Println(json) }
https://zhuanlan.zhihu.com/p/390439745
https://copyfuture.com/blogs-details/20210708162035291A