Go
Inline-Erweiterung
Suche…
Bemerkungen
Inline-Erweiterung ist eine häufige Optimierung in kompiliertem Code, bei der die Leistung der binären Größe vorrangig zugeordnet wurde. Der Compiler kann einen Funktionsaufruf durch den eigentlichen Rumpf der Funktion ersetzen. effektiv Code kopieren / einfügen von einer Stelle an eine andere zur Kompilierzeit. Da die Aufrufstelle so erweitert ist, dass sie nur die Maschinenbefehle enthält, die der Compiler für die Funktion generiert hat, müssen wir kein CALL oder PUSH (das x86-Äquivalent einer GOTO-Anweisung oder eines Stack-Frame-Pushs) oder das entsprechende Äquivalent auf einem anderen ausführen Architekturen.
Der Inliner entscheidet, ob eine Funktion basierend auf einer Reihe von Heuristiken inline gesetzt werden soll oder nicht, im Allgemeinen jedoch standardmäßig Inline. Da der Inliner Funktionsaufrufe loswird, kann er effektiv entscheiden, wo der Scheduler eine Goroutine ablehnen darf.
Funktionsaufrufe werden nicht eingebettet, wenn eine der folgenden Bedingungen zutrifft (es gibt viele andere Gründe, diese Liste ist unvollständig):
- Funktionen sind variadisch (zB haben sie
...
args) - Funktionen haben eine "max hairyness", die über dem Budget liegt (sie rezyklieren zu stark oder können aus einem anderen Grund nicht analysiert werden)
- Sie enthalten
panic
,recover
sich oderdefer
Deaktivieren der Inline-Erweiterung
Die Inline-Erweiterung kann mit dem go:noinline
Pragma go:noinline
. Wenn wir beispielsweise das folgende einfache Programm erstellen:
package main
func printhello() {
println("Hello")
}
func main() {
printhello()
}
wir erhalten eine Ausgabe, die so aussieht (auf Lesbarkeit getrimmt):
$ 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
…
Beachten Sie, dass es keinen CALL
printhello
an printhello
. Wenn wir dann das Programm mit dem Pragma erstellen, dann:
package main
//go:noinline
func printhello() {
println("Hello")
}
func main() {
printhello()
}
Die Ausgabe enthält die printhello-Funktion und einen 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
…