Hero Image
Golang基准测试

Golang 基准测试 基本使用 基准测试常用于代码性能测试,函数需要导入 testing 包,并定义以 Benchmark 开头的函数, 参数为 testing.B 指针类型,在测试函数中循环调用函数多次 ➜ go test -bench=. -run=none goos: darwin goarch: amd64 pkg: pkg06 cpu: Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz BenchmarkFib-12 250 4682682 ns/op PASS ok pkg06 1.875s ➜ go test -bench=. -benchmem -run=none goos: darwin goarch: amd64 pkg: pkg06 cpu: Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz BenchmarkFib-12 249 4686452 ns/op 0 B/op 0 allocs/op PASS ok pkg06 1.854s bench 的工作原理 基准测试函数会被一直调用直到 b.N 无效,它是基准测试循环的次数 b.N 从 1 开始,如果基准测试函数在 1 秒内就完成 (默认值),则 b.N 增加,并再次运行基准测试函数 b.N 的值会按照序列 1,2,5,10,20,50,... 增加,同时再次运行基准测测试函数 上述结果解读代表 1 秒内运行了 250 次,每次 4682682 ns -12 后缀和用于运行次测试的 GOMAXPROCS 值有关。与 GOMAXPROCS 一样,此数字默认为启动时 Go 进程可见的 CPU 数。可以使用 -cpu 标识更改此值,可以传入多个值以列表形式来运行基准测试 传入 cpu num 进行测试 ➜ go test -bench=. -cpu=1,2,4 -benchmem -run=none goos: darwin goarch: amd64 pkg: pkg06 cpu: Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz BenchmarkFib 244 4694667 ns/op 0 B/op 0 allocs/op BenchmarkFib-2 255 4721201 ns/op 0 B/op 0 allocs/op BenchmarkFib-4 256 4756392 ns/op 0 B/op 0 allocs/op PASS ok pkg06 5.826s count 多次运行基准测试 因为热缩放、内存局部性、后台处理、gc 活动等等会导致单次的误差,所以一般会进行多次测试

Hero Image
Gin中文文档

自定义路由日志的格式 Gin 运行多个服务 XML、JSON、YAML 和 ProtoBuf 渲染(输出格式) 自定义路由日志的格式 default [GIN-debug] POST /foo --> main.main.func1 (3 handlers) [GIN-debug] GET /bar --> main.main.func2 (3 handlers) [GIN-debug] GET /status --> main.main.func3 (3 handlers) import ( "log" "net/http" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() gin.DebugPrintRouteFunc = func(httpMethod, absolutePath, handlerName string, nuHandlers int) { log.Printf("endpoint %v %v %v %v\n", httpMethod, absolutePath, handlerName, nuHandlers) } r.POST("/foo", func(c *gin.Context) { c.JSON(http.StatusOK, "foo") }) r.GET("/bar", func(c *gin.Context) { c.JSON(http.StatusOK, "bar") }) r.GET("/status", func(c *gin.Context) { c.JSON(http.StatusOK, "ok") }) // Listen and Server in http://0.0.0.0:8080 r.Run() } Gin 运行多个服务 package main import ( "log" "net/http" "time" "github.com/gin-gonic/gin" "golang.org/x/sync/errgroup" ) var ( g errgroup.Group ) func router01() http.Handler { e := gin.New() e.Use(gin.Recovery()) e.GET("/", func(c *gin.Context) { c.JSON( http.StatusOK, gin.H{ "code": http.StatusOK, "error": "Welcome server 01", }, ) }) return e } func router02() http.Handler { e := gin.New() e.Use(gin.Recovery()) e.GET("/", func(c *gin.Context) { c.JSON( http.StatusOK, gin.H{ "code": http.StatusOK, "error": "Welcome server 02", }, ) }) return e } func main() { server01 := &http.Server{ Addr: ":8080", Handler: router01(), ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, } server02 := &http.Server{ Addr: ":8081", Handler: router02(), ReadTimeout: 5 * time.Second, WriteTimeout: 10 * time.Second, } g.Go(func() error { return server01.ListenAndServe() }) g.Go(func() error { return server02.ListenAndServe() }) if err := g.Wait(); err != nil { log.Fatal(err) } } XML、JSON、YAML 和 ProtoBuf 渲染(输出格式) SecureJSON 使用 SecureJSON 可以防止 json 劫持,如果返回的数据是数组,则会默认在返回值前加上"while(1)"