From 25f9af666194f81741aed8ea422661bd58149d30 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Felix=20Geisend=C3=B6rfer?= Date: Mon, 13 Mar 2023 09:56:45 +0100 Subject: [PATCH] runtime: add a benchmark of FPCallers MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This allows comparing frame pointer unwinding against the default unwinder as shown below. goos: linux goarch: amd64 pkg: runtime cpu: Intel(R) Xeon(R) Platinum 8375C CPU @ 2.90GHz │ callers.txt │ │ sec/op │ Callers/cached-32 1.254µ ± 0% FPCallers/cached-32 24.99n ± 0% For #16638 Change-Id: I4dd05f82254726152ef4a5d5beceab33641e9d2b Reviewed-on: https://go-review.googlesource.com/c/go/+/475795 TryBot-Result: Gopher Robot Run-TryBot: Felix Geisendörfer Reviewed-by: Michael Knyszek Reviewed-by: Cherry Mui --- src/runtime/callers_test.go | 20 ++++++++++++++++++++ src/runtime/export_test.go | 6 ++++++ 2 files changed, 26 insertions(+) diff --git a/src/runtime/callers_test.go b/src/runtime/callers_test.go index d738076a2f..e52357f175 100644 --- a/src/runtime/callers_test.go +++ b/src/runtime/callers_test.go @@ -430,3 +430,23 @@ func callersNoCache(b *testing.B, n int) int { return 1 + callersNoCache(b, n-1) } } + +func BenchmarkFPCallers(b *testing.B) { + b.Run("cached", func(b *testing.B) { + // Very pcvalueCache-friendly, no inlining. + fpCallersCached(b, 100) + }) +} + +func fpCallersCached(b *testing.B, n int) int { + if n <= 0 { + pcs := make([]uintptr, 32) + b.ResetTimer() + for i := 0; i < b.N; i++ { + runtime.FPCallers(0, pcs) + } + b.StopTimer() + return 0 + } + return 1 + fpCallersCached(b, n-1) +} diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index 367362b672..498c63f5b6 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -1727,3 +1727,9 @@ func FrameStartLine(f *Frame) int { func PersistentAlloc(n uintptr) unsafe.Pointer { return persistentalloc(n, 0, &memstats.other_sys) } + +// FPCallers works like Callers and uses frame pointer unwinding to populate +// pcBuf with the return addresses of the physical frames on the stack. +func FPCallers(skip int, pcBuf []uintptr) int { + return fpTracebackPCs(unsafe.Pointer(getcallerfp()), skip, pcBuf) +} -- 2.50.0