Skip to content

Instantly share code, notes, and snippets.

@life1347 life1347/benchmark.go
Last active Nov 11, 2019

Embed
What would you like to do?
Logrus v.s Zap
package main
import (
"encoding/json"
"fmt"
"log"
"time"
logrus "github.com/Sirupsen/logrus"
zap "go.uber.org/zap"
)
type dummy struct {
Foo string `json:"foo"`
Bar string `json:"bar"`
}
func main() {
dummyLog := dummy{
Foo: "foo",
Bar: "bar",
}
var x int64 = 0
for i := 0; i < 10000; i++ {
t := time.Now()
logrus.WithField("Dummy", dummyLog).Infoln("this is a dummy log")
x += time.Since(t).Nanoseconds()
}
zlogger, _ := zap.NewProduction()
sugar := zlogger.Sugar()
var y int64 = 0
for i := 0; i < 10000; i++ {
t := time.Now()
sugar.Infow("this is a dummy log", "Dummy", dummyLog)
y += time.Since(t).Nanoseconds()
}
var z int64 = 0
for i := 0; i < 10000; i++ {
t := time.Now()
dummyStr, _ := json.Marshal(dummyLog)
log.Printf("this is a dummy log: %s\n", string(dummyStr))
z += time.Since(t).Nanoseconds()
}
fmt.Println("=====================")
fmt.Printf("Logrus: %5d ns per request \n", x/10000)
fmt.Printf("Zap: %5d ns per request \n", y/10000)
fmt.Printf("StdLog: %5d ns per request \n", z/10000)
}
/*
Logrus: 8309 ns per request
Zap: 730 ns per request
StdLog: 4433 ns per request
*/
@utkarshmani1997

This comment has been minimized.

Copy link

utkarshmani1997 commented Feb 21, 2018

Thanks @life1347, i would like to add glog's benchmark also.

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"time"

	"github.com/golang/glog"

	logrus "github.com/Sirupsen/logrus"
	zap "go.uber.org/zap"
)

type dummy struct {
	Foo string `json:"foo"`
	Bar string `json:"bar"`
}

func main() {
	dummyLog := dummy{
		Foo: "foo",
		Bar: "bar",
	}

	var x int64 = 0
	for i := 0; i < 10000; i++ {
		t := time.Now()
		logrus.WithField("Dummy", dummyLog).Infoln("this is a dummy log")
		x += time.Since(t).Nanoseconds()
	}

	zlogger, _ := zap.NewProduction()
	sugar := zlogger.Sugar()

	var y int64 = 0
	for i := 0; i < 10000; i++ {
		t := time.Now()
		sugar.Infow("this is a dummy log", "Dummy", dummyLog)
		y += time.Since(t).Nanoseconds()
	}

	var z int64 = 0
	for i := 0; i < 10000; i++ {
		t := time.Now()
		dummyStr, _ := json.Marshal(dummyLog)
		log.Printf("this is a dummy log: %s\n", string(dummyStr))
		z += time.Since(t).Nanoseconds()
	}

	var w int64 = 0
	for i := 0; i < 10000; i++ {
		t := time.Now()
		glog.Info("\nthis is a dummy log: ", dummyLog)
		w += time.Since(t).Nanoseconds()
	}
	fmt.Println("=====================")
	fmt.Printf("Logrus: %5d ns per request \n", x/10000)
	fmt.Printf("Zap:    %5d ns per request \n", y/10000)
	fmt.Printf("StdLog: %5d ns per request \n", z/10000)
	fmt.Printf("Glog:   %5d ns per request \n", w/10000)
}

/*
Logrus: 17964 ns per request 
Zap:     2836 ns per request 
StdLog:  8768 ns per request 
Glog:   22445 ns per request
*/
@utkarshmani1997

This comment has been minimized.

Copy link

utkarshmani1997 commented Feb 21, 2018

@life1347 do you have any idea why glog and others performs good as compared to zap if no of loops are less?

@godcong

This comment has been minimized.

Copy link

godcong commented May 14, 2019

use random string and map test

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"math/rand"
	"time"

	"github.com/golang/glog"

	"github.com/sirupsen/logrus"
	"go.uber.org/zap"
)

type dummy struct {
	Foo string `json:"foo"`
	Bar string `json:"bar"`
}

const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
const (
	letterIdxBits = 6                    // 6 bits to represent a letter index
	letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
	letterIdxMax  = 63 / letterIdxBits   // # of letter indices fitting in 63 bits
)

func RandString(n int) string {
	b := make([]byte, n)
	// A rand.Int63() generates 63 random bits, enough for letterIdxMax letters!
	for i, cache, remain := n-1, rand.Int63(), letterIdxMax; i >= 0; {
		if remain == 0 {
			cache, remain = rand.Int63(), letterIdxMax
		}
		if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
			b[i] = letterBytes[idx]
			i--
		}
		cache >>= letterIdxBits
		remain--
	}
	return string(b)
}

func dummyMap()map[string]string  {
	return map[string]string{
		RandString(6): RandString(12),
		RandString(8): RandString(16),
	}
}

func dummyData() interface{} {
	return dummy{
		Foo: RandString(12),
		Bar: RandString(16),
	}
}

func main() {
	var x int64 = 0
	t := time.Now()
	for i := 0; i < 10000; i++ {
		logrus.WithField("Dummy", dummyData()).Infoln("this is a dummy log")
	}
	x += time.Since(t).Nanoseconds()
	zlogger, _ := zap.NewProduction()
	sugar := zlogger.Sugar()
	var y int64 = 0
	t = time.Now()
	for i := 0; i < 10000; i++ {
		sugar.Infow("this is a dummy log", "Dummy", dummyData())
	}
	y += time.Since(t).Nanoseconds()
	var z int64 = 0
	t = time.Now()
	for i := 0; i < 10000; i++ {
		dummyStr, _ := json.Marshal(dummyData())
		log.Printf("this is a dummy log: %s\n", string(dummyStr))
	}
	z += time.Since(t).Nanoseconds()
	var w int64 = 0
	t = time.Now()
	for i := 0; i < 10000; i++ {
		glog.Info("\nthis is a dummy log: ", dummyData())
	}
	w += time.Since(t).Nanoseconds()
	fmt.Println("=====================")
	fmt.Printf("Logrus: %5d ns per request \n", x/10000)
	fmt.Printf("Zap:    %5d ns per request \n", y/10000)
	fmt.Printf("StdLog: %5d ns per request \n", z/10000)
	fmt.Printf("Glog:   %5d ns per request \n", w/10000)
}

/*
Logrus: 45298 ns per request
Zap:     1799 ns per request
StdLog: 13099 ns per request
Glog:   24399 ns per request
*/
@aoliang

This comment has been minimized.

Copy link

aoliang commented Nov 11, 2019

you case is not so good. first, log.Printf log json data and other case does not encode json data which takes expensive cost, making log.Printf is not so well. second, sugar.Infow take less cost, but sugar.With("Dummy", dummyLog).Info("this is a dummy log") takes more cost than logrus.WithField("Dummy", dummyData()).Infoln("this is a dummy log"). so i conclude, the best log depends what to log, how to log (like json forma\text format\other format)and how to use these framework API.

package lumber

import (
	"testing"

	"github.com/sirupsen/logrus"
	"go.uber.org/zap"
)

type dummy struct {
	Foo string `json:"foo"`
	Bar string `json:"bar"`
}

const times = 100000

func TestCase1(t *testing.T) {
	dummyLog := dummy{
		Foo: "foo",
		Bar: "bar",
	}
	for i := 0; i < times; i++ {
		logrus.WithField("Dummy", dummyLog).Info("this is a dummy log")
	}
}

func TestCase2(t *testing.T) {
	dummyLog := dummy{
		Foo: "foo",
		Bar: "bar",
	}
	zlogger, _ := zap.NewProduction()
	sugar := zlogger.Sugar()

	for i := 0; i < times; i++ {
		sugar.With("Dummy", dummyLog).Info("this is a dummy log")
	}
}

image

but, zap takes less time per request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.