Skip to content

Commit

Permalink
improve caller performance
Browse files Browse the repository at this point in the history
  • Loading branch information
phuslu committed Apr 24, 2024
1 parent 94168fe commit 52d68b6
Show file tree
Hide file tree
Showing 8 changed files with 335 additions and 32 deletions.
7 changes: 3 additions & 4 deletions logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 := pcFileLine(pc)
if !fullpath {
var i int
for i = len(file) - 1; i >= 0; i-- {
Expand All @@ -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)
}
Expand Down
14 changes: 0 additions & 14 deletions logger_go1.18.go

This file was deleted.

14 changes: 0 additions & 14 deletions logger_go1.22.go

This file was deleted.

53 changes: 53 additions & 0 deletions runtime_go1.18.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//go:build go1.18 && !go1.19
// +build go1.18,!go1.19

package log

import (
"runtime"
_ "unsafe"
)

type funcID uint8

type funcInfo struct {
_func *uintptr
datap unsafe.Pointer
}

func pcFileLine(pc uintptr) (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--
}

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 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.fastrandn
func Fastrandn(x uint32) uint32
53 changes: 53 additions & 0 deletions runtime_go1.19.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//go:build go1.19 && !go1.20
// +build go1.19,!go1.20

package log

import (
"runtime"
_ "unsafe"
)

type funcID uint8

type funcInfo struct {
_func *uintptr
datap unsafe.Pointer
}

func pcFileLine(pc uintptr) (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--
}

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 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.fastrandn
func Fastrandn(x uint32) uint32
53 changes: 53 additions & 0 deletions runtime_go1.20.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//go:build go1.20 && !go1.21
// +build go1.20,!go1.21

package log

import (
"runtime"
_ "unsafe"
)

type funcID uint8

type funcInfo struct {
_func *uintptr
datap unsafe.Pointer
}

func pcFileLine(pc uintptr) (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--
}

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 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.fastrandn
func Fastrandn(x uint32) uint32
53 changes: 53 additions & 0 deletions runtime_go1.21.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//go:build go1.21 && !go1.22
// +build go1.21,!go1.22

package log

import (
"runtime"
_ "unsafe"
)

type funcID uint8

type funcInfo struct {
_func *uintptr
datap unsafe.Pointer
}

func pcFileLine(pc uintptr) (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--
}

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 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.fastrandn
func Fastrandn(x uint32) uint32
120 changes: 120 additions & 0 deletions runtime_go1.22.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
//go:build go1.22 && !go1.23
// +build go1.22,!go1.23

package log

import (
"unsafe"
)

type funcID uint8

type funcInfo struct {
_func *uintptr
datap unsafe.Pointer
}

func pcFileLine(pc uintptr) (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--
}

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 funcline1 runtime.funcline1
func funcline1(f funcInfo, targetpc uintptr, strict bool) (file string, line int32)

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 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

// Fastrandn returns a pseudorandom uint32 in [0,n).
//
//go:noescape
//go:linkname Fastrandn runtime.cheaprandn
func Fastrandn(x uint32) uint32

0 comments on commit 52d68b6

Please sign in to comment.