From 38ee5f7d5371ea6aebeb56d18bc715ae32872505 Mon Sep 17 00:00:00 2001 From: John Date: Wed, 30 Oct 2019 15:12:19 +0800 Subject: [PATCH] improve performance of gdebug --- .example/debug/gdebug/gdebug.go | 1 + .example/other/test.go | 9 +-- debug/gdebug/gdebug.go | 65 +++++++++++-------- debug/gdebug/gdebug_bench_test.go | 104 ++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+), 34 deletions(-) create mode 100644 debug/gdebug/gdebug_bench_test.go diff --git a/.example/debug/gdebug/gdebug.go b/.example/debug/gdebug/gdebug.go index ad767d3c7..2410096a9 100644 --- a/.example/debug/gdebug/gdebug.go +++ b/.example/debug/gdebug/gdebug.go @@ -6,6 +6,7 @@ import ( ) func main() { + gdebug.PrintStack() fmt.Println(gdebug.CallerPackage()) fmt.Println(gdebug.CallerFunction()) } diff --git a/.example/other/test.go b/.example/other/test.go index 02d872135..1b23932a2 100644 --- a/.example/other/test.go +++ b/.example/other/test.go @@ -1,12 +1,7 @@ package main -import ( - "github.com/gogf/gf/internal/intlog" -) +import "github.com/gogf/gf/debug/gdebug" func main() { - intlog.Print(1, 2, 3) - intlog.Printf("%d", 1) - intlog.Error(1) - intlog.Errorf("%d", 1) + gdebug.PrintStack() } diff --git a/debug/gdebug/gdebug.go b/debug/gdebug/gdebug.go index 335ef3e59..5961f3aa6 100644 --- a/debug/gdebug/gdebug.go +++ b/debug/gdebug/gdebug.go @@ -23,7 +23,7 @@ import ( const ( gMAX_DEPTH = 1000 - gFILTER_KEY = "/debug/gdebug/gdebug.go" + gFILTER_KEY = "/debug/gdebug/gdebug" ) var ( @@ -92,14 +92,19 @@ func StackWithFilters(filters []string, skip ...int) string { index := 1 buffer := bytes.NewBuffer(nil) filtered := false - for i := callerFromIndex(filters) + number; i < gMAX_DEPTH; i++ { - if pc, file, line, ok := runtime.Caller(i); ok { + ok := true + pc, file, line, start := callerFromIndex(filters) + for i := start + number; i < gMAX_DEPTH; i++ { + if i != start { + pc, file, line, ok = runtime.Caller(i) + } + if ok { if goRootForFilter != "" && len(file) >= len(goRootForFilter) && file[0:len(goRootForFilter)] == goRootForFilter { continue } filtered = false for _, filter := range filters { - if strings.Contains(file, filter) { + if filter != "" && strings.Contains(file, filter) { filtered = true break } @@ -140,36 +145,43 @@ func CallerWithFilter(filter string, skip ...int) (function string, path string, if len(skip) > 0 { number = skip[0] } - for i := callerFromIndex([]string{filter}) + number; i < gMAX_DEPTH; i++ { - if pc, file, line, ok := runtime.Caller(i); ok { - if filter != "" && strings.Contains(file, filter) { - continue + ok := true + pc, file, line, start := callerFromIndex([]string{filter}) + if start != -1 { + for i := start + number; i < gMAX_DEPTH; i++ { + if i != start { + pc, file, line, ok = runtime.Caller(i) } - if strings.Contains(file, gFILTER_KEY) { - continue - } - function := "" - if fn := runtime.FuncForPC(pc); fn == nil { - function = "unknown" + if ok { + if filter != "" && strings.Contains(file, filter) { + continue + } + if strings.Contains(file, gFILTER_KEY) { + continue + } + function := "" + if fn := runtime.FuncForPC(pc); fn == nil { + function = "unknown" + } else { + function = fn.Name() + } + return function, file, line } else { - function = fn.Name() + break } - return function, file, line - } else { - break } } return "", "", -1 } -// callerFromIndex returns the caller position exclusive of the debug package. -func callerFromIndex(filters []string) int { - filtered := false - for i := 0; i < gMAX_DEPTH; i++ { - if _, file, _, ok := runtime.Caller(i); ok { +// callerFromIndex returns the caller position and according information exclusive of the debug package. +func callerFromIndex(filters []string) (pc uintptr, file string, line int, index int) { + var filtered, ok bool + for index = 0; index < gMAX_DEPTH; index++ { + if pc, file, line, ok = runtime.Caller(index); ok { filtered = false for _, filter := range filters { - if strings.Contains(file, filter) { + if filter != "" && strings.Contains(file, filter) { filtered = true break } @@ -180,11 +192,10 @@ func callerFromIndex(filters []string) int { if strings.Contains(file, gFILTER_KEY) { continue } - // exclude the depth from the function of current package. - return i - 1 + return } } - return 0 + return 0, "", -1, -1 } // CallerPackage returns the package name of the caller. diff --git a/debug/gdebug/gdebug_bench_test.go b/debug/gdebug/gdebug_bench_test.go new file mode 100644 index 000000000..8c6dbda69 --- /dev/null +++ b/debug/gdebug/gdebug_bench_test.go @@ -0,0 +1,104 @@ +// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +// go test *.go -bench=".*" -benchmem + +package gdebug + +import ( + "runtime" + "testing" +) + +func Benchmark_BinVersion(b *testing.B) { + for i := 0; i < b.N; i++ { + BinVersion() + } +} + +func Benchmark_BinVersionMd5(b *testing.B) { + for i := 0; i < b.N; i++ { + BinVersionMd5() + } +} + +func Benchmark_RuntimeCaller(b *testing.B) { + for i := 0; i < b.N; i++ { + runtime.Caller(0) + } +} + +func Benchmark_RuntimeFuncForPC(b *testing.B) { + for i := 0; i < b.N; i++ { + runtime.FuncForPC(11010101) + } +} + +func Benchmark_callerFromIndex(b *testing.B) { + for i := 0; i < b.N; i++ { + callerFromIndex(nil) + } +} + +func Benchmark_Stack(b *testing.B) { + for i := 0; i < b.N; i++ { + Stack() + } +} + +func Benchmark_StackWithFilter(b *testing.B) { + for i := 0; i < b.N; i++ { + StackWithFilter("test") + } +} + +func Benchmark_Caller(b *testing.B) { + for i := 0; i < b.N; i++ { + Caller() + } +} + +func Benchmark_CallerWithFilter(b *testing.B) { + for i := 0; i < b.N; i++ { + CallerWithFilter("test") + } +} + +func Benchmark_CallerFilePath(b *testing.B) { + for i := 0; i < b.N; i++ { + CallerFilePath() + } +} + +func Benchmark_CallerDirectory(b *testing.B) { + for i := 0; i < b.N; i++ { + CallerDirectory() + } +} + +func Benchmark_CallerFileLine(b *testing.B) { + for i := 0; i < b.N; i++ { + CallerFileLine() + } +} + +func Benchmark_CallerFileLineShort(b *testing.B) { + for i := 0; i < b.N; i++ { + CallerFileLineShort() + } +} + +func Benchmark_CallerFunction(b *testing.B) { + for i := 0; i < b.N; i++ { + CallerFunction() + } +} + +func Benchmark_CallerPackage(b *testing.B) { + for i := 0; i < b.N; i++ { + CallerPackage() + } +}