当前位置:网站首页>Technical dry goods | understand go memory allocation
Technical dry goods | understand go memory allocation
2022-06-24 05:24:00 【Tencent cloud Ti platform】
author :rocketwang
If you're also a Go developer , Do you care about memory allocation and recycling ? The created object needs to be created by GC To recycle , Or as the call stack is ejected , Just disappeared ? GC As a result of Stop The World Does it cause the performance jitter of your program ?
This article briefly introduces Go Memory allocation logic , It introduces Go Memory partition model . And take the code as an example , Briefly introduce several scenarios Go Memory allocation logic . Subsequent use go build The command verifies the memory escape and other related verifications . Last , Summed up the memory allocation principles .
Need to care about memory allocation
Every engineer's time is so precious , Before continuing to read this article , I need you to answer a few questions first , If the answer is no , Maybe the content in this article doesn't help you . however , If you encounter performance problems caused by memory allocation , Maybe this article can help you understand Golang The tip of the iceberg of memory allocation , Take you through the door .
Questions as follows :
- Is your program performance sensitive ?
- GC Does the delay affect the performance of your program ?
- Does your program have excessive heap memory allocation ?
If you hit one or both of the above questions , This article is suitable for you to continue reading . Or you don't know how to answer these questions , Maybe go and find out go Knowledge related to performance observation (pprof Use, etc. ) More helpful to you .
The following text begins .
Golang Brief memory partition
We can simply think that Golang When the program starts , A certain area of memory will be requested from the operating system , Divided into stacks (Stack) And heaps (Heap). Stack memory will be allocated and recycled as the function is called ; Heap memory is allocated by a program request , By the garbage collector (Garbage Collector) Responsible for recycling . On the performance , Stack memory is used and recycled more quickly ; Even though Golang Of GC Very efficient , But it will inevitably bring some performance losses . therefore ,Go Give priority to using stack memory for memory allocation . When you have to allocate objects to the heap , To put a specific object on the heap .
Memory allocation process analysis
This part , Will be in the form of code , Introduce stack memory allocation respectively 、 Stack memory allocation with pointer as parameter 、 The stack memory allocation in the case of pointer as return value gradually leads to escape analysis and several basic principles of memory escape .
Text begins ,Talk is cheap,show me the code.
Stack memory allocation
I will use a simple code as an example , Analyze the memory allocation process of this code .
package main
import "fmt"
func main() { n := 4 n2 := square(n) fmt.Println(n2)}
func square(n int) int{ return n * n}The function of the code is very simple , One main Function as program entry , Defines a variable n, Defines another function squire , Returns the result of the power operation int value . Last , Print the returned value to the console . The program output is 16.
Let's start the analysis line by line , When parsing the call ,go How the runtime allocates memory .
When the code runs to the 6 That's ok , Get into main Function time , Will create a on the stack Stack frame, Store the variable information in this function . Include function name , Variable etc. .
When the code runs to the 7 Line time ,go A new one will be pushed into the stack Stack Frame, Used to store calls square Function information ; Include function name 、 Variable n And so on . here , Calculation 4 * 4 Value , And back to .
When square Function call completed , return 16 To main After the function , take 16 Assign a value to n2 Variable . Be careful , The original stack frame It's not going to be go Clean up , Instead, as the arrow on the left side of the stack shows , Marked as illegal . The horizontal line between the red arrow and the green arrow in the above figure can be understood as go In assembly code SP The value of the stack register , When a program requests or frees stack memory , It just needs to be modified SP Register value , This stack memory allocation method saves the time of cleaning up the stack memory space 【1】.
Next , call fmt.Println when ,SP The value of the register will increase further , Cover up the original square Functional stack frame, complete print after , Program exit normally .
Stack memory allocation with pointer as parameter
The same process , Look at the following code .
package main
import "fmt"
func main() { n := 4 increase(&n) fmt.Println(n)}
func increase(i *int) { *i++}main As program entry , Declared a variable n, The assignment is 4. Declared a function increase, Use one int Pointer to type i As a parameter ,increase Within the function , To the pointer i The corresponding value is automatically increased . Last main The function prints n Value . The program output is 5.
When the program runs to main The function of the first 6 Line time ,go A... Is allocated on the stack stack frame , The variable n It's assigned ,n The corresponding address in memory is 0xc0008771, At this point, the program will continue to execute downward , call increase function .
At this time ,increase Function corresponding stack fream Be created ,i Is assigned as a variable n Corresponding address value 0xc0008771, Then carry out the auto increment operation .
When increase When the function is finished ,SP The register will move up , Put the previously assigned stack freme Marked as illegal . here , The program runs normally , Not because SP Register changes affect the correctness of the program , The values in memory are also modified correctly .
Stack memory allocation with pointer as return value
The previous part of the article introduced the stack memory usage when ordinary variables are used as parameters and pointers are used as parameters , This section describes how to use a pointer as a return value , Return to the caller , How memory is allocated , And introduce the related contents of memory escape . Look at this code :
package main
import "fmt"
func main() { n := initValue() fmt.Println(*n/2)}
func initValue() *int { i := 4 return &i}main Function , Called initValue function , This function returns a int Pointer and assign to n, The value corresponding to the pointer is 4. And then ,main Function call fmt.Println Printed pointer n / 2 Corresponding value . The program output is 2.
Program call initValue after , take i Assign the address of to the variable n . Be careful , If this time , Variable i On the stack , May be overwritten at any time .
Calling fmt.Println when ,Stack Frame Will be recreated , Variable i To be an assignment *n/2 That is to say 2, Will cover the original n The value of the variable pointed to . This can lead to extremely serious problems . In the face of sharing up Scene time ,go Variables are usually allocated to the heap , As shown in the figure below :
Through the above analysis , You can see that assigning objects to the stack when the called function returns a pointer type can cause serious problems , therefore Go Allocated variables to the heap . This distribution ensures the security of the program , But it also inevitably increases heap memory creation , And at some point in the future , need GC Clean up unused memory .
Principle of memory allocation
After the above analysis , You can simply sum up a few principles .
- Sharing down typically stays on the stack Variables or objects created at the caller , Passed to the called function in the form of parameters , At this time , The memory space created at the caller is usually on the stack . This creates memory at the caller , When the callee uses the memory “ Memory sharing ” The way , be called Sharing down.
- Sharing up typically escapes to the heap The object created in the called function , When it is returned to the caller as a pointer , Usually , The created memory space is on the heap . This is created by the callee , Used by the caller “ Memory sharing ” The way , be called Sharing up.
- Only the compiler knows The reason why the above two principles both add the usual , Because of the specific distribution method , Is determined by the compiler , Some compiler backend optimizations , May break through these two principles , therefore , Specific allocation logic , Only the compiler ( Or people who develop compilers ) know .
Use go build The command determines the memory escape condition
It is worth noting that ,Go In determining whether a variable or object needs to escape to the heap , Is completed in the compiler ; in other words , When the code is written , After compiler compilation , Specific annotations will be made in binary , Declare that the specified variable is to be allocated to the heap or stack . You can print out the memory allocation logic at compile time using the following command , To know the memory allocation location of a specific variable or object .
see go help You can see go build It's actually calling go tool compile.
go help build ... -gcflags '[pattern=]arg list' arguments to pass on each go tool compile invocation....
go tool compile -h...-m print optimization decisions...-l disable inlining...
among , There are two parameters that need to be concerned ,
- -m Show optimization decisions
- -l Inline is prohibited 【2】
The code is as follows :
package main
func main() { n := initValue() println(*n / 2)
o := initObj() println(o)
f := initFn() println(f)
num := 5 result := add(num) println(result)}
func initValue() *int { i := 3 // ./main.go:19:2: moved to heap: i return &i}
type Obj struct { i int}
func initObj() *Obj { return &Obj{i: 3} // ./main.go:28:9: &Obj literal escapes to heap}
func initFn() func() { return func() { // ./main.go:32:9: func literal escapes to heap println("I am a function") }}
func add(i int) int { return i + 1}The complete build command and output are as follows :
go build -gcflags="-m -l" # _/Users/rocket/workspace/stack-or-heap./main.go:19:2: moved to heap: i./main.go:24:9: &Obj literal escapes to heap./main.go:28:9: func literal escapes to heap
You can see ,sharing up The situation of (initValue,initObj,initFn) Memory space is allocated to the heap .sharing down The situation of (add) Memory space is on the stack .
Here is a question for the reader , You can study moved to heap and escapes to heap The difference between .
summary
1. Because stack is more efficient than heap , Unwanted GC, therefore Go Will allocate memory to the stack as much as possible .
2. When allocated to the stack, it may cause illegal memory access and other problems , Can use heap , The main scenes are :
- When a value may be accessed after a function is called , This value is most likely allocated to the heap .
- When the compiler detects that a value is too large , This value will be allocated to the heap .
- When compiling , The compiler does not know the size of this value (slice、map...) This value will be allocated to the heap .
3.Sharing down typically stays on the stack
4.Sharing up typically escapes to the heap
5.Don't guess, Only the compiler knows
reference
【1】Go Language design and implementation :https://draveness.me/golang/docs/part3-runtime/ch07-memory/golang-stack-management/#%E5%AF%84%E5%AD%98%E5%99%A8
【2】Inlining optimisations in Go:https://dave.cheney.net/2020/04/25/inlining-optimisations-in-go
【3】Golang FAQ:https://golang.org/doc/faq#stack_or_heap
边栏推荐
- Panoramic recording, WYSIWYG new recording scheme, and exclusive preferential resource package as low as 1 yuan!
- Oceanus practice - use of the Nepal graph connector in the graph database
- What is the implementation of domain name to IP address conversion? What are the benefits of switching to a website?
- What is stored in the domain name server? How does the domain name server provide services?
- Use cloud functions to receive callbacks and cooperate with CLS to view callback logs and persistent storage
- What is domain name filing? What is the role of domain name filing?
- What domain name is cheap? How much does it cost to register a domain name?
- The easyplayer player displays compileerror:webassembly Reason for instance() and its solution
- Spirit breath development log (9)
- Blackmail virus prevention guide
猜你喜欢

How should we learn cloud native in 2022?

Intensive learning and application of "glory of the king" to complete the application of 7 real worlds other than human players
Easy to understand JDBC tutorial - absolutely suitable for zero Foundation
What cloud native knowledge should programmers master?

CTF learning notes 18:iwesec file upload vulnerability-03-content-type filtering bypass

How does win10 turn off f1~f12 shortcut keys?
![[leetcode daily question] push domino](/img/81/1c31e97d9a245816514bcf47c92107.jpg)
[leetcode daily question] push domino

CTF learning notes 17:iwesec file upload vulnerability-02 file name filtering bypass

Hard core observation 553 AI needs to identify almost everyone in the world with hundreds of billions of photos

Answer questions! This article explains the automated testing framework in software testing from beginning to end
随机推荐
Error 0xc0000013, 0xc000007b, etc. due to the conflict between the CD-ROM drive letter and the drive letter in the business program path
How to expand virtual machine capacity on vSphere client
How to apply for company website domain name how to build a website after domain name registration
How should we learn cloud native in 2022?
Spirit breath development log (7)
Svg quick start small white article
Net is what domain name? What is the standard of a good domain name?
What server does domain name and IP address convert through? How does the server convert?
How to register a company domain name how to build a website with a domain name
How to register an overseas domain name what should be paid attention to when registering a domain name
Analysis of PHP environment configuration
Build your unique online image
What domain name is Io? The role of domain name for web address
How unity runs code every few frames
What is the meaning of Xin domain name? What is the performance in network applications
What is primary domain name? What are the divisions of domain names
System design: Agent & redundancy & replication
Three methods of local storage
What domain name does not need to be filed? What should be done for domain name filing
Panoramic recording, WYSIWYG new recording scheme, and exclusive preferential resource package as low as 1 yuan!