Go
Expansion Inline
Recherche…
Remarques
L'expansion en ligne est une optimisation courante du code compilé qui privilégie les performances par rapport à la taille binaire. Il permet au compilateur de remplacer un appel de fonction par le corps même de la fonction; copier / coller efficacement du code d'un endroit à un autre au moment de la compilation. Comme le site d’appel est développé pour contenir uniquement les instructions machine générées par le compilateur pour la fonction, nous n’avons pas à exécuter un appel CALL ou PUSH (l’équivalent x86 d’une instruction GOTO ou d’un push de cadre) ou leur équivalent sur d’autres des architectures.
L'inliner prend des décisions sur l'inclusion ou non d'une fonction basée sur un certain nombre d'heuristiques, mais en général, Go s'intègre par défaut. Parce que l'inliner se débarrasse des appels de fonction, il parvient effectivement à décider où le planificateur est autorisé à préempter une goroutine.
Les appels de fonction ne seront pas mis en ligne si l’une des conditions suivantes est vraie (il y a également beaucoup d’autres raisons, cette liste est incomplète):
- Les fonctions sont variadiques (par exemple, elles ont
...
args) - Les fonctions ont un "maximum de cheveux" supérieur au budget (elles se répètent trop ou ne peuvent pas être analysées pour une autre raison)
- Ils contiennent la
panic
,recover
oudefer
Désactiver l'extension en ligne
L'expansion en ligne peut être désactivée avec le pragma go:noinline
. Par exemple, si nous construisons le programme simple suivant:
package main
func printhello() {
println("Hello")
}
func main() {
printhello()
}
nous obtenons une sortie qui ressemble à ceci (ajustée pour la lisibilité):
$ go version
go version go1.6.2 linux/amd64
$ go build main.go
$ ./main
Hello
$ go tool objdump main
TEXT main.main(SB) /home/sam/main.go
main.go:7 0x401000 64488b0c25f8ffffff FS MOVQ FS:0xfffffff8, CX
main.go:7 0x401009 483b6110 CMPQ 0x10(CX), SP
main.go:7 0x40100d 7631 JBE 0x401040
main.go:7 0x40100f 4883ec10 SUBQ $0x10, SP
main.go:8 0x401013 e8281f0200 CALL runtime.printlock(SB)
main.go:8 0x401018 488d1d01130700 LEAQ 0x71301(IP), BX
main.go:8 0x40101f 48891c24 MOVQ BX, 0(SP)
main.go:8 0x401023 48c744240805000000 MOVQ $0x5, 0x8(SP)
main.go:8 0x40102c e81f290200 CALL runtime.printstring(SB)
main.go:8 0x401031 e89a210200 CALL runtime.printnl(SB)
main.go:8 0x401036 e8851f0200 CALL runtime.printunlock(SB)
main.go:9 0x40103b 4883c410 ADDQ $0x10, SP
main.go:9 0x40103f c3 RET
main.go:7 0x401040 e87b9f0400 CALL runtime.morestack_noctxt(SB)
main.go:7 0x401045 ebb9 JMP main.main(SB)
main.go:7 0x401047 cc INT $0x3
main.go:7 0x401048 cc INT $0x3
main.go:7 0x401049 cc INT $0x3
main.go:7 0x40104a cc INT $0x3
main.go:7 0x40104b cc INT $0x3
main.go:7 0x40104c cc INT $0x3
main.go:7 0x40104d cc INT $0x3
main.go:7 0x40104e cc INT $0x3
main.go:7 0x40104f cc INT $0x3
…
noter qu'il n'y a pas CALL
à printhello
. Cependant, si nous construisons ensuite le programme avec le pragma en place:
package main
//go:noinline
func printhello() {
println("Hello")
}
func main() {
printhello()
}
La sortie contient la fonction printhello et un CALL main.printhello
:
$ go version
go version go1.6.2 linux/amd64
$ go build main.go
$ ./main
Hello
$ go tool objdump main
TEXT main.printhello(SB) /home/sam/main.go
main.go:4 0x401000 64488b0c25f8ffffff FS MOVQ FS:0xfffffff8, CX
main.go:4 0x401009 483b6110 CMPQ 0x10(CX), SP
main.go:4 0x40100d 7631 JBE 0x401040
main.go:4 0x40100f 4883ec10 SUBQ $0x10, SP
main.go:5 0x401013 e8481f0200 CALL runtime.printlock(SB)
main.go:5 0x401018 488d1d01130700 LEAQ 0x71301(IP), BX
main.go:5 0x40101f 48891c24 MOVQ BX, 0(SP)
main.go:5 0x401023 48c744240805000000 MOVQ $0x5, 0x8(SP)
main.go:5 0x40102c e83f290200 CALL runtime.printstring(SB)
main.go:5 0x401031 e8ba210200 CALL runtime.printnl(SB)
main.go:5 0x401036 e8a51f0200 CALL runtime.printunlock(SB)
main.go:6 0x40103b 4883c410 ADDQ $0x10, SP
main.go:6 0x40103f c3 RET
main.go:4 0x401040 e89b9f0400 CALL runtime.morestack_noctxt(SB)
main.go:4 0x401045 ebb9 JMP main.printhello(SB)
main.go:4 0x401047 cc INT $0x3
main.go:4 0x401048 cc INT $0x3
main.go:4 0x401049 cc INT $0x3
main.go:4 0x40104a cc INT $0x3
main.go:4 0x40104b cc INT $0x3
main.go:4 0x40104c cc INT $0x3
main.go:4 0x40104d cc INT $0x3
main.go:4 0x40104e cc INT $0x3
main.go:4 0x40104f cc INT $0x3
TEXT main.main(SB) /home/sam/main.go
main.go:8 0x401050 64488b0c25f8ffffff FS MOVQ FS:0xfffffff8, CX
main.go:8 0x401059 483b6110 CMPQ 0x10(CX), SP
main.go:8 0x40105d 7606 JBE 0x401065
main.go:9 0x40105f e89cffffff CALL main.printhello(SB)
main.go:10 0x401064 c3 RET
main.go:8 0x401065 e8769f0400 CALL runtime.morestack_noctxt(SB)
main.go:8 0x40106a ebe4 JMP main.main(SB)
main.go:8 0x40106c cc INT $0x3
main.go:8 0x40106d cc INT $0x3
main.go:8 0x40106e cc INT $0x3
main.go:8 0x40106f cc INT $0x3
…