~/talk

Implementing Faster Defers

Talkat GopherCon 2020 · 2020-11-09..11-13· [go]
links:none on file
slides:none on file

Explains how Go implements open-coded defers by storing function pointers and args in stack slots and flipping a defer bits bitmap so most defers avoid runtime allocations and calls. Adds func metadata (funcdata) so the runtime can reconstruct active defers during a panic. Claims Go 1.14 cuts defer overhead from ~44 ns (Go 1.12) to ~32 ns (Go 1.13) to ~3 ns for the common case versus a 1.7 ns plain call.

AI-written summary · about

  1. 0:00Intro
  2. 0:28Defer Statement • defer keyword followed by a function or method call The function pointer and arguments are evaluated immediately, but the call is deferred until the current function finishes • The call is guaranteed to be called on any exit from the function, normal or panic • New language construct in Go
  3. 2:19Defer Performance Goal Goal for defer optimization in Go 1.14 • Make defor overhead low enough that programmers can use defer in any function whenever it is helpful • End the common belief that defers can be expensive
  4. 3:04Related language constructs • RAll (Resource Acquisition is Initialization) - C++
  5. 6:30Advantages of Defer • Improves maintainability: guarantees cleanup will happen even if more function exits are added • Improves robustness: guarantees cleanup will happen even if there is a panic - especially important for recovered panics (eg. long-running web server) • Improves clarity-cleanup operation is described immediately following the relevant code • Expresses conditional cleanup nicely
  6. 8:26Implementing Go's Defer • Defer is completely dynamic (can be called inside a loop, conditional etc.) • A straightforward implementation must be handled by the Go runtime, in order to deal with the dynamic cases • The unusual cases (defer in a loop) can be expensive to handle But the common, simple cases are statically analyzable, and we would like these cases to be as efficient as C++ RAIL
  7. 10:21Defer chain • Linked list of currently active defer records Each defer record contains function pointer, defer args, pointer to stack frame Each defer record may be on stack or heap (if defer is in a loop)
  8. 11:15Defer chain & panics • runtime gopanic processes defer records in LIFO order as well: Calls the appropriate function with the defer args Continues until all defer records are processed, or one of the
  9. 12:22Idea: make deferred calls directly in simple cases . Only applicable for functions where no defer statement is in a loop • At defer statements, compiler generates code to evaluate and store into stack slots the function pointer and any args, and to set
  10. 15:00Compiler notes for open-coded defers • We must ensure that the defer arguments are stored to their stack slots (not just kept in registers), so they are available in case of panic • Similarly, updates to deferits must be stored on the stack
  11. 15:50Panic processing for open-coded defers • How to handle panics - we don't have a defer record any more... • Record in funcdata all the information about each defer, including stack slots where the function pointer and args are stored, etc. "fundata" is extra information in the Go binary that can be
  12. 21:33Future optimizations • Eliminate deferBits check for any unconditional defer (even when other defers are conditional) • Use constant arguments directly in the defer calls at exit • Do inlining of deferred calls not currently done because inlining precedes defer statement
~/search
type to search 6,249 conferences, 138,987 speakers and 185,172 talks
~/help
cmdctrl k
search every conference, speaker and series
/
focus the filter search
h
home
c
conferences
s
speakers
e
series
t
light / dark — the status bar button does the same
?
this help
esc
close this, then clear every filter — or just the search, while you are typing in it

Ignored while you are typing. Pages without a filter rail have no search to focus.