Go
Inline Expansion
Szukaj…
Uwagi
Rozszerzanie wbudowane jest powszechną optymalizacją w skompilowanym kodzie, w której wydajność jest ważniejsza niż rozmiar binarny. Pozwala kompilatorowi zamienić wywołanie funkcji na rzeczywistą treść funkcji; efektywnie kopiuj / wklejaj kod z jednego miejsca do drugiego w czasie kompilacji. Ponieważ witryna wywołań jest rozszerzona, aby zawierała tylko instrukcje maszynowe generowane przez kompilator dla tej funkcji, nie musimy wykonywać CALL ani PUSH (ekwiwalent x86 instrukcji GOTO lub push ramki stosu) ani ich odpowiednika w innych architektury.
Inliner decyduje, czy wstawić funkcję na podstawie szeregu heurystyk, ale ogólnie domyślnie wstawia funkcję Go. Ponieważ inliner pozbywa się wywołań funkcji, skutecznie decyduje, gdzie program planujący może zablokować goroutine.
Wywołania funkcji nie będą wstawiane, jeśli spełniony jest jeden z poniższych warunków (istnieje również wiele innych powodów, lista jest niekompletna):
- Funkcje są różne (np. Mają
...
argumenty) - Funkcje mają „maksimum owłosienia” większe niż budżet (zbyt często się powtarzają lub z innych powodów nie mogą być analizowane)
- Zawierają
panic
,recover
lubdefer
Wyłączanie wbudowanego rozszerzenia
Rozszerzanie go:noinline
można wyłączyć za pomocą go:noinline
pragma. Na przykład, jeśli zbudujemy następujący prosty program:
package main
func printhello() {
println("Hello")
}
func main() {
printhello()
}
otrzymujemy dane wyjściowe wyglądające tak (przycięte dla czytelności):
$ 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
…
zwróć uwagę, że nie ma CALL
do printhello
. Jeśli jednak zbudujemy program z pragmą:
package main
//go:noinline
func printhello() {
println("Hello")
}
func main() {
printhello()
}
Dane wyjściowe zawierają funkcję printhello i 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
…