From f2415ebc0f9bdace23e176674773c78c5c9d8bee Mon Sep 17 00:00:00 2001 From: phuslu Date: Wed, 24 Apr 2024 01:39:50 +0800 Subject: [PATCH] improve caller performance for go1.22 --- logger.go | 7 ++-- logger_go1.18.go | 14 ------- logger_go1.22.go | 14 ------- runtime_go1.18.go | 21 ++++++++++ runtime_go1.19.go | 21 ++++++++++ runtime_go1.20.go | 21 ++++++++++ runtime_go1.21.go | 21 ++++++++++ runtime_go1.22.go | 100 ++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 187 insertions(+), 32 deletions(-) delete mode 100644 logger_go1.18.go delete mode 100644 logger_go1.22.go create mode 100644 runtime_go1.18.go create mode 100644 runtime_go1.19.go create mode 100644 runtime_go1.20.go create mode 100644 runtime_go1.21.go create mode 100644 runtime_go1.22.go diff --git a/logger.go b/logger.go index fb478613..ac1fef98 100644 --- a/logger.go +++ b/logger.go @@ -1741,9 +1741,8 @@ func (e *Entry) caller(n int, pc uintptr, fullpath bool) { if n < 1 { return } - rpc := [1]uintptr{pc} - frame, _ := runtime.CallersFrames(rpc[:]).Next() - file := frame.File + + _, file, line := pcNameFileLine(pc) if !fullpath { var i int for i = len(file) - 1; i >= 0; i-- { @@ -1759,7 +1758,7 @@ func (e *Entry) caller(n int, pc uintptr, fullpath bool) { e.buf = append(e.buf, ",\"caller\":\""...) e.buf = append(e.buf, file...) e.buf = append(e.buf, ':') - e.buf = strconv.AppendInt(e.buf, int64(frame.Line), 10) + e.buf = strconv.AppendInt(e.buf, int64(line), 10) e.buf = append(e.buf, "\",\"goid\":"...) e.buf = strconv.AppendInt(e.buf, int64(goid()), 10) } diff --git a/logger_go1.18.go b/logger_go1.18.go deleted file mode 100644 index e653d509..00000000 --- a/logger_go1.18.go +++ /dev/null @@ -1,14 +0,0 @@ -//go:build go1.18 && !go1.22 -// +build go1.18,!go1.22 - -package log - -import ( - _ "unsafe" -) - -// Fastrandn returns a pseudorandom uint32 in [0,n). -// -//go:noescape -//go:linkname Fastrandn runtime.fastrandn -func Fastrandn(x uint32) uint32 diff --git a/logger_go1.22.go b/logger_go1.22.go deleted file mode 100644 index 5565d94f..00000000 --- a/logger_go1.22.go +++ /dev/null @@ -1,14 +0,0 @@ -//go:build go1.22 -// +build go1.22 - -package log - -import ( - _ "unsafe" -) - -// Fastrandn returns a pseudorandom uint32 in [0,n). -// -//go:noescape -//go:linkname Fastrandn runtime.cheaprandn -func Fastrandn(x uint32) uint32 diff --git a/runtime_go1.18.go b/runtime_go1.18.go new file mode 100644 index 00000000..55aed8d1 --- /dev/null +++ b/runtime_go1.18.go @@ -0,0 +1,21 @@ +//go:build go1.18 && !go1.19 +// +build go1.18,!go1.19 + +package log + +import ( + "runtime" + _ "unsafe" +) + +func pcNameFileLine(pc uintptr) (name, file string, line int) { + rpc := [1]uintptr{pc} + frame, _ := runtime.CallersFrames(rpc[:]).Next() + return "", frame.File, frame.Line +} + +// Fastrandn returns a pseudorandom uint32 in [0,n). +// +//go:noescape +//go:linkname Fastrandn runtime.fastrandn +func Fastrandn(x uint32) uint32 diff --git a/runtime_go1.19.go b/runtime_go1.19.go new file mode 100644 index 00000000..357fef0d --- /dev/null +++ b/runtime_go1.19.go @@ -0,0 +1,21 @@ +//go:build go1.19 && !go1.20 +// +build go1.19,!go1.20 + +package log + +import ( + "runtime" + _ "unsafe" +) + +func pcNameFileLine(pc uintptr) (name, file string, line int) { + rpc := [1]uintptr{pc} + frame, _ := runtime.CallersFrames(rpc[:]).Next() + return "", frame.File, frame.Line +} + +// Fastrandn returns a pseudorandom uint32 in [0,n). +// +//go:noescape +//go:linkname Fastrandn runtime.fastrandn +func Fastrandn(x uint32) uint32 diff --git a/runtime_go1.20.go b/runtime_go1.20.go new file mode 100644 index 00000000..1feb98f0 --- /dev/null +++ b/runtime_go1.20.go @@ -0,0 +1,21 @@ +//go:build go1.20 && !go1.21 +// +build go1.20,!go1.21 + +package log + +import ( + "runtime" + _ "unsafe" +) + +func pcNameFileLine(pc uintptr) (name, file string, line int) { + rpc := [1]uintptr{pc} + frame, _ := runtime.CallersFrames(rpc[:]).Next() + return "", frame.File, frame.Line +} + +// Fastrandn returns a pseudorandom uint32 in [0,n). +// +//go:noescape +//go:linkname Fastrandn runtime.fastrandn +func Fastrandn(x uint32) uint32 diff --git a/runtime_go1.21.go b/runtime_go1.21.go new file mode 100644 index 00000000..c9ce1352 --- /dev/null +++ b/runtime_go1.21.go @@ -0,0 +1,21 @@ +//go:build go1.21 && !go1.22 +// +build go1.21,!go1.22 + +package log + +import ( + "runtime" + _ "unsafe" +) + +func pcNameFileLine(pc uintptr) (name, file string, line int) { + rpc := [1]uintptr{pc} + frame, _ := runtime.CallersFrames(rpc[:]).Next() + return "", frame.File, frame.Line +} + +// Fastrandn returns a pseudorandom uint32 in [0,n). +// +//go:noescape +//go:linkname Fastrandn runtime.fastrandn +func Fastrandn(x uint32) uint32 diff --git a/runtime_go1.22.go b/runtime_go1.22.go new file mode 100644 index 00000000..897cd203 --- /dev/null +++ b/runtime_go1.22.go @@ -0,0 +1,100 @@ +//go:build go1.22 && !go1.23 +// +build go1.22,!go1.23 + +package log + +import ( + "unsafe" +) + +type PC uintptr + +type funcID uint8 + +type funcInfo struct { + _func *uintptr + datap unsafe.Pointer +} + +type inlinedCall struct { + funcID funcID // type of the called function + _ [3]byte + nameOff int32 // offset into pclntab for name of called function + parentPc int32 // position of an instruction whose source position is the call site (offset from entry) + startLine int32 // line number of start of function (func keyword/TEXT directive) +} + +type inlineUnwinder struct { + f funcInfo + inlTree *[1 << 20]inlinedCall +} + +type inlineFrame struct { + pc uintptr + index int32 +} + +type srcFunc struct { + datap *uintptr + nameOff int32 + startLine int32 + funcID funcID +} + +func pcNameFileLine(pc uintptr) (name, file string, line int) { + funcInfo := findfunc(pc) + if funcInfo._func == nil { + return + } + + entry := funcInfoEntry(funcInfo) + + if pc > entry { + // We store the pc of the start of the instruction following + // the instruction in question (the call or the inline mark). + // This is done for historical reasons, and to make FuncForPC + // work correctly for entries in the result of runtime.Callers. + pc-- + } + + // It's important that interpret pc non-strictly as cgoTraceback may + // have added bogus PCs with a valid funcInfo but invalid PCDATA. + u, uf := newInlineUnwinder(funcInfo, pc) + sf := inlineUnwinder_srcFunc(&u, uf) + + name = funcNameForPrint(srcFunc_name(sf)) + file, line32 := funcline1(funcInfo, pc, false) + line = int(line32) + + return +} + +//go:linkname findfunc runtime.findfunc +func findfunc(pc uintptr) funcInfo + +//go:linkname funcInfoEntry runtime.funcInfo.entry +func funcInfoEntry(f funcInfo) uintptr + +//go:linkname newInlineUnwinder runtime.newInlineUnwinder +func newInlineUnwinder(f funcInfo, pc uintptr) (inlineUnwinder, inlineFrame) + +//go:linkname inlineUnwinder_srcFunc runtime.(*inlineUnwinder).srcFunc +func inlineUnwinder_srcFunc(*inlineUnwinder, inlineFrame) srcFunc + +//go:linkname inlineUnwinder_isInlined runtime.(*inlineUnwinder).isInlined +func inlineUnwinder_isInlined(*inlineUnwinder, inlineFrame) bool + +//go:linkname srcFunc_name runtime.srcFunc.name +func srcFunc_name(srcFunc) string + +//go:linkname funcNameForPrint runtime.funcNameForPrint +func funcNameForPrint(name string) string + +//go:linkname funcline1 runtime.funcline1 +func funcline1(f funcInfo, targetpc uintptr, strict bool) (file string, line int32) + +// Fastrandn returns a pseudorandom uint32 in [0,n). +// +//go:noescape +//go:linkname Fastrandn runtime.cheaprandn +func Fastrandn(x uint32) uint32