수색…
비고
인라인 확장은 바이너리 크기보다 성능을 우선시하는 컴파일 된 코드의 일반적인 최적화입니다. 컴파일러는 함수 호출을 함수의 실제 본문으로 대체 할 수 있습니다. 컴파일 타임에 효과적으로 한 곳에서 다른 곳으로 코드 복사 / 붙여 넣기. 호출 사이트는 컴파일러가 함수에 대해 생성 한 시스템 명령어를 포함하도록 확장 되었기 때문에 CALL 또는 PUSH (GOTO 문의 스택 또는 스택 프레임 푸시에 해당하는 x86) 또는 그와 동등한 것을 수행 할 필요가 없습니다 아키텍처.
인라이너는 여러 가지 추론을 기반으로 함수를 인라인할지 여부를 결정하지만 일반적으로 기본적으로 인라인으로 이동합니다. inliner는 함수 호출을 없애기 때문에 스케줄러가 goroutine을 선점 할 수있는 위치를 효과적으로 결정합니다.
함수 호출은 다음 중 하나라도 해당되면 인라인되지 않습니다 (다른 많은 이유도 있지만이 목록은 불완전합니다).
- 함수는 가변적입니다 (예 : arg
...
). - 함수는 예산보다 큰 "최대 털이"를가집니다 (너무 많이 재발하거나 다른 이유로 분석 할 수 없음)
- 그들은
panic
,recover
또는defer
인라인 확장 사용 중지
인라인 확장은 go:noinline
pragma go:noinline
비활성화 할 수 있습니다. 예를 들어, 다음과 같은 간단한 프로그램을 빌드하면 :
package main
func printhello() {
println("Hello")
}
func main() {
printhello()
}
우리는 다음과 같은 출력을 얻습니다 (가독성을 위해 조정).
$ 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
…
printhello
대한 CALL
이 없음을 printhello
. 그러나, 만약 우리가 프라그마 (pragma)를 사용하여 프로그램을 빌드한다면 :
package main
//go:noinline
func printhello() {
println("Hello")
}
func main() {
printhello()
}
출력에는 printhello 함수와 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
…
Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow