Overview
Syllabus
Intro
Defer 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
Defer 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
Related language constructs • RAll (Resource Acquisition is Initialization) - C++
Advantages 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
Implementing 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
Defer 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)
Defer 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
Idea: 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
Compiler 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
Panic 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
Future 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
Taught by
Gopher Academy