Ezreal 书架 Ezreal 书架
Home
  • 《Go程序员面试笔试宝典》
  • 《RabbitMQ 实战指南》
  • 《深入理解kafka》
  • MySQL45讲
  • 透视HTTP协议
  • 结构化数据的分布式存储系统
  • Raft 共识算法
Home
  • 《Go程序员面试笔试宝典》
  • 《RabbitMQ 实战指南》
  • 《深入理解kafka》
  • MySQL45讲
  • 透视HTTP协议
  • 结构化数据的分布式存储系统
  • Raft 共识算法
  • 逃逸分析

    • 逃逸分析是什么
    • 逃逸分析有什么作用
    • 逃逸分析是怎么完成的
    • 如何确定是否发生逃逸
    • Go与其他语言的堆和栈是同一个概念吗
  • 延迟语句

  • 数据容器

  • 通道

  • 接口

  • unsafe

  • context

  • Go程序员面试笔试宝典
  • 逃逸分析
ezreal_rao
2023-04-23

如何确定是否发生逃逸

Go 提供了相关的命令,可以查看变量是否发生逃逸。使用前面提到的例子:

package main

import "fmt"

func main() {
	x := foo()
	fmt.Println(*x)
}

func foo() *int {
	t := 3
	return &t
}
1
2
3
4
5
6
7
8
9
10
11
12
13

foo 函数返回一个局部变量的指针,使用 main 函数里变量 x 接收它。执行如下命令:

go build -gcflags '-m -l' main.go
1

其中 -gcflags 参数用于启用编译器支持的额外标志。例如,-m 用于输出编译器的优化细节(包括使用逃逸分析这种优化),相反可以使用 -N 来关闭编译器优化;而 -l 则用于禁用 foo 函数的内联优化,防止逃逸被编译器通过内联彻底的抹除。得到如下输出:

# command-line-arguments
./main.go:11:2: moved to heap: t
./main.go:7:13: ... argument does not escape
./main.go:7:14: *x escapes to heap
1
2
3
4

foo 函数里的变量 t 逃逸了,和预想的一致,不解的是为什么 main 函数里的 x 也逃逸了? 这是因为有些函数的参数为 interface 类型,比如 fmt.Println (a ...interface {}),编译期间很难确定其参数的具体类型,也会发生逃逸。

使用反汇编命令也可以看出变量是否发生逃逸。执行命令:

截取部分结果如图 1-1 所示,图中标记出来的函数 newobject 用于在堆上分配一块内存,从而说明 t 被存放到了堆上,也就是发生了逃逸。

反汇编结果

#逃逸分析
上次更新: 5/9/2023, 10:58:32 AM
逃逸分析是怎么完成的
Go与其他语言的堆和栈是同一个概念吗

← 逃逸分析是怎么完成的 Go与其他语言的堆和栈是同一个概念吗→

最近更新
01
为什么我的MySQL会抖一下
07-15
02
HTTP 性能优化面面观
07-12
03
WebSocket:沙盒里的 TCP
07-12
更多文章>
Theme by Vdoing | Copyright © 2022-2024 Ezreal Rao | CC BY-NC-SA 4.0
豫ICP备2023001810号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式