当前位置:网站首页>Golang memory escape
Golang memory escape
2022-04-23 05:04:00 【canger_】
Escape analysis
Memory escape : The phenomenon that the memory on the stack escapes to the heap is called memory escape
Concept
The program confirms which variables are allocated in the stack area according to the code in the compilation stage , Which variables are allocated in the heap . This prevents too much memory from being allocated on the heap , reduce GC Pressure and procedure STW Time for
principle
-
Pointers to stack objects cannot be stored in the heap
-
A pointer to a stack object cannot exceed the lifetime of the object , That is, the pointer cannot survive after the stack object is destroyed
How to view
By compiling the code in the following way, you can see the escape analysis
go build -gcflags='-m -m -l'
- -m -m You can see all compiler optimizations
- -l Disable inline optimization
Analyze examples
Function returns a pointer to a local variable
package main
type st struct {
a int
b int
}
func Add(x, y int) *st {
r := st{
a: x, b: y}
return &r
}
func main() {
res := Add(3, 5)
res.a = 10
}
See the escape analysis results
$ go build -gcflags="-m -m -l" test.go
# command-line-arguments
./test.go:9:2: r escapes to heap:
./test.go:9:2: flow: ~r2 = &r:
./test.go:9:2: from &r (address-of) at ./test.go:10:9
./test.go:9:2: from return &r (return) at ./test.go:10:2
./test.go:9:2: moved to heap: r
note: module requires Go 1.17
You can see the local variable pointer r Memory escape occurred
Function returns a local variable
package main
type st struct {
a int
b int
}
func Add(x, y int) st {
r := st{
a: x, b: y}
return r
}
func main() {
res := Add(3, 5)
res.a = 10
}
Escape analysis
$ go build -gcflags="-m -m -l" test.go
$
- There is no information , It means there is no escape
interface Type escape
package main
import "fmt"
func main() {
res := 10
fmt.Print(res)
}
Escape analysis
$ go build -gcflags="-m -m -l" test.go
# command-line-arguments
./test.go:7:11: res escapes to heap:
./test.go:7:11: flow: {
storage for ... argument} = &{
storage for res}:
./test.go:7:11: from res (spill) at ./test.go:7:11
./test.go:7:11: from ... argument (slice-literal-element) at ./test.go:7:11
./test.go:7:11: flow: {
heap} = {
storage for ... argument}:
./test.go:7:11: from ... argument (spill) at ./test.go:7:11
./test.go:7:11: from fmt.Print(... argument...) (call parameter) at ./test.go:7:11
./test.go:7:11: ... argument does not escape
./test.go:7:11: res escapes to heap
note: module requires Go 1.17
You can see res There was an escape , This is because :
- The compiler is hard to determine interface{} Specific types of , So there will be an escape
But we can see that res There is no such thing as move to heap
, This is because the compiler just puts res The stored value is stored in the heap ,res Itself is still in the stack area , But we can make the following changes :
package main
import "fmt"
func main() {
res := 10
fmt.Print(&res)
}
Escape analysis
$ go build -gcflags="-m -m -l" test.go
# command-line-arguments
./test.go:6:2: res escapes to heap:
./test.go:6:2: flow: {
storage for ... argument} = &res:
./test.go:6:2: from &res (address-of) at ./test.go:7:12
./test.go:6:2: from &res (interface-converted) at ./test.go:7:12
./test.go:6:2: from ... argument (slice-literal-element) at ./test.go:7:11
./test.go:6:2: flow: {
heap} = {
storage for ... argument}:
./test.go:6:2: from ... argument (spill) at ./test.go:7:11
./test.go:6:2: from fmt.Print(... argument...) (call parameter) at ./test.go:7:11
./test.go:6:2: moved to heap: res
./test.go:7:11: ... argument does not escape
note: module requires Go 1.17
Will find ,res They also escaped to the pile area , This is because fmt.Print
The output is res The address of , Therefore, the compiler will store the value of the address in the heap , But objects on the heap cannot store an address on the stack , Because after the stack variable is destroyed , Its address is invalid , The address stored in that heap will also be invalid , Therefore, it is necessary to res Also escaped to the pile area .
Escape from closure
package main
func add() func() int {
num := 0
f := func() int {
num++
return num
}
return f
}
func main() {
add()
}
Escape analysis :
$ go build -gcflags="-m -m -l" test.go
# command-line-arguments
./test.go:6:3: add.func1 capturing by ref: num (addr=true assign=true width=8)
./test.go:5:7: func literal escapes to heap:
./test.go:5:7: flow: f = &{
storage for func literal}:
./test.go:5:7: from func literal (spill) at ./test.go:5:7
./test.go:5:7: from f := func literal (assign) at ./test.go:5:4
./test.go:5:7: flow: ~r0 = f:
./test.go:5:7: from return f (return) at ./test.go:9:2
./test.go:4:2: num escapes to heap:
./test.go:4:2: flow: {
storage for func literal} = &num:
./test.go:4:2: from func literal (captured by a closure) at ./test.go:5:7
./test.go:4:2: from num (reference) at ./test.go:6:3
./test.go:4:2: moved to heap: num
./test.go:5:7: func literal escapes to heap
note: module requires Go 1.17
You can see f And in closures num Memory escapes have occurred . Because a function is also a pointer type , Therefore, as a return value, escape also occurs . And as long as you call f, Will call num, therefore num You also need to escape to the pile area
Variable size is uncertain or stack space is insufficient
- When the stack space is enough , There will be no escape , But when the variable is too large , Has completely exceeded the size of the stack space , There will be an escape to the heap to allocate memory
- When initializing slices , No size is specified directly , Instead, fill in the variables , In this case, in order to ensure the safety of memory , The compiler also triggers an escape , Allocate memory on the heap
towards channel Send pointer data
package main
func main() {
ch1 := make(chan *int, 1)
y := 5
py := &y
ch1 <- py
}
Escape analysis
$ go build -gcflags="-m -m -l" test.go
# command-line-arguments
./test.go:5:2: y escapes to heap:
./test.go:5:2: flow: py = &y:
./test.go:5:2: from &y (address-of) at ./test.go:6:8
./test.go:5:2: from py := &y (assign) at ./test.go:6:5
./test.go:5:2: flow: {heap} = py:
./test.go:5:2: from ch1 <- py (send) at ./test.go:7:6
./test.go:5:2: moved to heap: y
note: module requires Go 1.17
The compiler cannot know channel The data in will be used by goroutine receive , There is no way to know when to release
summary
- Escape analysis determines which variables can be allocated on the stack at the compilation stage , Which variables are allocated on the heap
- To reduce the GC pressure , The running speed of the provider
- When the memory on the stack is used up, you don't need GC Handle , When the memory on the heap is used up, it will be handed over to GC Handle
- Minimize escape code , reduce GC pressure
版权声明
本文为[canger_]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204220552063585.html
边栏推荐
- Making message board with PHP + MySQL
- 信息学奥赛一本通 1955:【11NOIP普及组】瑞士轮 | OpenJudge 4.1 4363:瑞士轮 | 洛谷 P1309 [NOIP2011 普及组] 瑞士轮
- This call when the transaction does not take effect
- Download PDF from HowNet (I don't want to use CAJViewer anymore!!!)
- vscode ipynb文件没有代码高亮和代码补全解决方法
- [database] MySQL single table query
- COM in wine (2) -- basic code analysis
- What are the redis data types
- C# List字段排序含有数字和字符
- Wechat payment function
猜你喜欢
Uglifyjs compress JS
多线程基本概念(并发与并行、线程与进程)和入门案例
Deep learning notes - data expansion
独立站运营 | FaceBook营销神器——聊天机器人ManyChat
持续集成(CI)/持续交付(CD)如何彻底改变自动化测试
[2022 ICLR] Pyraformer: Low-Complexity Pyramidal Attention for Long-Range 时空序列建模和预测
[2021] Spatio-Temporal Graph Contrastive Learning
Opencv + clion face recognition + face model training
Pixel 5 5g unlocking tutorial (including unlocking BL, installing edxposed and root)
AQS源码阅读
随机推荐
Custom switch control
Analysis of POM files
Progress of innovation training (III)
Transaction isolation level of MySQL transactions
Day.js 常用方法
The applet calls the function of scanning QR code and jumps to the path specified by QR code
【数据库】MySQL基本操作(基操~)
Painless upgrade of pixel series
Barcode generation and decoding, QR code generation and decoding
Cross border e-commerce | Facebook and instagram: which social media is more suitable for you?
Learning Android from scratch -- Introduction
Use the built-in function of win to transfer files between two computers in the same LAN (the speed is the same as that between local disks)
A trinomial expression that causes a null pointer
[2021] Spatio-Temporal Graph Contrastive Learning
DIY is an excel version of subnet calculator
Leetcode 1547: minimum cost of cutting sticks
Unity C# 网络学习(四)
JS détermine si la chaîne de nombres contient des caractères
Independent station operation | Facebook marketing artifact - chat robot manychat
[winui3] Écrivez une copie du gestionnaire de fichiers Explorer