• uber.zap性能验证


    一、性能基准测试

    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

  • 相关阅读:
    echarts的legend图例的显示与隐藏(legend折线图加载完页面显示的个数)
    程序员必备网站
    web前端兼容性问题总结
    sass
    JS 中的事件绑定、事件监听、事件委托是什么?
    格式化电话号码,并不像看到的那么简单
    机器学习之Javascript篇: k-Means 聚类算法介绍
    机器学习之Javascript篇:遗传算法(2)
    机器学习之Javascript篇:遗传算法介绍
    机器学习之Javascript篇: 近邻(k-nearest-neighbor) 算法介绍
  • 原文地址:https://www.cnblogs.com/xuweiqiang/p/16379748.html
Copyright © 2020-2023  润新知