From 51cb12e83b87a100d1df0d80f5176417e08872ea Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 3 Aug 2023 13:52:00 -0700 Subject: [PATCH] runtime: add deferreturn fast path for linked defers A consequence of go.dev/cl/513837 was that calling deferreturn would now use the unwinder to find (just) the current frame, and it turns out there are workloads where this has a significant performance impact. As a simple optimization, this CL adds a fast path for deferreturn to detect when there are pending linked defers, which allows us to skip invoking the unwinder entirely. Notably, this still doesn't handle the corner case of calling deferreturn in a function that uses linked defer when dynamically there just aren't any defers pending. It also means that after recovering from a panic and returning to a frame that used open-coded, we still need to use the unwinder too. I hope to further optimize defer handling to improve these cases too, but this is an easy, short-term optimization that relieves the performance impact to the affected workloads. Change-Id: I11fa73649302199eadccc27b403b231db8f33db2 Reviewed-on: https://go-review.googlesource.com/c/go/+/515716 Auto-Submit: Matthew Dempsky TryBot-Result: Gopher Robot Run-TryBot: Matthew Dempsky Reviewed-by: Keith Randall Reviewed-by: Keith Randall --- src/runtime/panic.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/runtime/panic.go b/src/runtime/panic.go index d3aaa20cbc..1ed40c71a4 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -638,6 +638,14 @@ func (p *_panic) start(pc uintptr, sp unsafe.Pointer) { if !p.deferreturn { p.link = gp._panic gp._panic = (*_panic)(noescape(unsafe.Pointer(p))) + } else { + // Fast path for deferreturn: if there's a pending linked defer + // for this frame, then we know there aren't any open-coded + // defers, and we don't need to find the parent frame either. + if d := gp._defer; d != nil && d.sp == uintptr(sp) { + p.sp = sp + return + } } // Initialize state machine, and find the first frame with a defer. -- 2.50.0