当前位置:网站首页>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
边栏推荐
- Excel uses the functions of replacement, sorting and filling to comprehensively sort out financial data
- 洛谷P2731骑马修栅栏
- L2-011 play binary tree (build tree + BFS)
- Deep learning notes - object detection and dataset + anchor box
- Introduction to load balancing
- Excel protects worksheets and workbooks from damage
- 持续集成(CI)/持续交付(CD)如何彻底改变自动化测试
- CLion+OpenCV identify ID number - detect ID number
- Transaction isolation level of MySQL transactions
- In aggregated query without group by, expression 1 of select list contains nonaggregated column
猜你喜欢
MySQL -- execution process and principle of a statement
Details related to fingerprint payment
[database] MySQL basic operation (basic operation ~)
深度学习笔记 —— 微调
【数据库】MySQL单表查询
【数据库】MySQL基本操作(基操~)
[2022 ICLR] Pyraformer: Low-Complexity Pyramidal Attention for Long-Range 时空序列建模和预测
Learning Android II from scratch - activity
Thoughts on a small program
Innovation training (IX) integration
随机推荐
Spell it! Two A-level universities and six B-level universities have abolished master's degree programs in software engineering!
Acid of MySQL transaction
MySQL -- execution process and principle of a statement
Progress of innovation training (IV)
#define 定义常量和宏,指针和结构体
scp命令详解
PHP+MySQL 制作留言板
AQS源码阅读
Graduation project
Opencv + clion face recognition + face model training
This call when the transaction does not take effect
calendar. Pit point of getactualmaximum (calendar. Day_of_month)
深度学习笔记 —— 数据增广
Agile practice | agile indicators to improve group predictability
Innovation training (II) task division
Arduino UNO r3+LCD1602+DHT11
Innovation training (10)
静态流水线和动态流水线的区别认识
PHP 统计指定文件夹下文件的数量
A trinomial expression that causes a null pointer