Defer in version 1.14

In Go1.14, there was another update to Defer, which reportedly increased the speed by an order of magnitude.

At compile time, defer is executed directly at the end of the function, eliminating the use of the _defer structure and linked list. The official name for this method is Open Coded.

However, open coding will not be used unless the following conditions are met:

  • Function of thedeferThe number is less than or equal to 8;
  • Function of thedeferKeywords cannot be executed in loops;
  • Function of thereturnStatements anddeferThe product of statements is less than or equal to 15;

Delay a bit

Why does it say that the number of defer should be less than or equal to 8? This is due to the delay bit limitation. There are only eight delay bits (the default is 0), each of which corresponds to one defer. The delay bit is used to determine whether the defer statement should be executed, for example:

package main

import "fmt"

func main(a) {
	i:=1
	if i==1{
		defer fmt.Println("defer")}}Copy the code

There is an if statement outside of defer, and when it is true, the corresponding defer bit is set to 1. Then, at the end of the function, each defer determines whether the corresponding bit-bit record is 1 and executes if it is, otherwise not.

Use time

In the current version, there are three ways to defer, so how does Go determine which one to use?

Code generation phase of the CMD/compile/internal/gc. State. The STMT will be responsible for the defer of the handler, the function will be according to different conditions, the use of three different kinds of mechanisms to deal with the key words:

func (s *state) stmt(n *Node){...switch n.Op {
	case ODEFER:
		if s.hasOpenDefers {
			s.openDeferRecord(n.Left) // Open encoding
		} else {
			d := callDefer / / heap allocation
			if n.Esc == EscNever {
				d = callDeferStack / / stack allocation
			}
			s.callResult(n.Left, d)
		}func (s *state) stmt(n *Node){... }}Copy the code

Panic problem

While defer in the latest version is very fast, when the program sends Panic, the normal logic after that does not execute and instead executes the defer linked list. Defer functions that are expanded in functions using ** open coded addresses and thus not registered in the linked list are found by stack scanning. So in version 1.14, several fields were added to assist with the stack scan of Panic.

review

  • 【defer】 Defer | Go theme month in 1.12
  • 【defer】 The defer | Go theme month in update 1.13