Advanced memory allocation
-
Upload
joris-bonnefoy -
Category
Software
-
view
142 -
download
0
Transcript of Advanced memory allocation
![Page 1: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/1.jpg)
Advanced memory allocation in Go
![Page 2: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/2.jpg)
Joris BonnefoyDevOps @ OVH@devatoria
![Page 3: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/3.jpg)
Before we get started...
![Page 4: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/4.jpg)
Keep it simple, readable
● Avoid premature optimizations○ Sometimes, readability and logicalness are better than performances
● Use go tools in order to point out real problems○ pprof
○ gcflags
![Page 5: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/5.jpg)
Introduction tomemory management
![Page 6: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/6.jpg)
Virtual and physical memory
● When you launch a new process, the kernel
creates its address space
● In this address space, the process can
allocate memory
● For the process, its address space looks like
a big contiguous memory space
● For two identical processes, (logical)
addresses can be the same○ Depending on the compiler, the architecture, ...
![Page 7: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/7.jpg)
Virtual and physical memory
● Each process has its own “memory
sandbox” called its virtual address
space
● Virtual addresses are mapped to
physical addresses by the CPU (and
the MMU component) using page
tables
● Per-process virtual space size is
4GB on 32-bits system and 256TB
on 64-bits one
![Page 8: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/8.jpg)
Virtual and physical memory
● Virtual address space is split into 2 spaces○ Kernel space
○ User mode space (or process address space)
● Split depends on operating system
configuration
![Page 9: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/9.jpg)
How is user space managed? (C example)
![Page 10: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/10.jpg)
Stack vs. Heap
![Page 11: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/11.jpg)
The stack● On the top of the process address space
○ Grows down
● Last In First Out design○ Cheap allocation cost
● Only one register is needed to track content○ Stack Pointer (SP register)
● Calling a function pushes a new stack frame
onto the stack
● Stack frame is destroyed on function return
● Each thread in a process has its own stack○ They share the same address space
● Stack size is limited, but can be expanded○ Until a certain limit, usually 8MB
![Page 12: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/12.jpg)
The heap
● Grows up
● Expensive allocation cost○ No specific data structure
● Complex management
● Used to allocate variables that must
outlive the function doing the allocation
● Fragmentation issues○ Contiguous free blocks can be merged
![Page 13: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/13.jpg)
Memory allocationin Go
![Page 14: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/14.jpg)
Like threads, goroutines have their own stack.
![Page 15: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/15.jpg)
<= Go 1.2 - Segmented stacks
● Discontiguous stacks
● Grows incrementally
● Each stack starts with a segment (8kB in Go 1.2)
● When stack is fulla. another segment is created and linked to the stack
b. stack segment is removed when not used anymore (stack is shrinked)
● Stacks are doubly-linked list
![Page 16: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/16.jpg)
<= Go 1.2 - Segmented stacks
![Page 17: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/17.jpg)
<= Go 1.2 - Hot split issue
![Page 18: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/18.jpg)
>= Go 1.3 - Copying stacks
● Contiguous stacks
● Each stack starts with a size of 2kB (since Go 1.4)
● When stack is fulla. a new stack is created, with the double size of the previous one
b. content of the old one is copied to the new one
c. pointers are re-adjusted
d. old one is destroyed
● Stack is never shrinked
![Page 19: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/19.jpg)
>= Go 1.3 - Copying stacks
![Page 20: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/20.jpg)
Benchmarks
![Page 21: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/21.jpg)
Efficient memoryallocation (and compileroptimizations)
![Page 22: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/22.jpg)
Reminders
Heap
(de)allocation
is expensive
Stack
(de)allocation
is cheap
![Page 23: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/23.jpg)
Reminders
Go manages memory automatically
![Page 24: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/24.jpg)
Reminders
Go prefers allocation on the stack
![Page 25: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/25.jpg)
Go functionsinlining
![Page 26: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/26.jpg)
Go functions inlining
● The code of the inlined function is inserted at the place of each call to this function
● No more assembly CALL instruction
● No need to create function stack frame● Binary size is increased because of the possible repetition of assembly instructions
● Can be disabled using //go:noinline comment just before the function declaration
![Page 27: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/27.jpg)
Go escapeanalysis system
![Page 28: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/28.jpg)
Escape analysis
● Decides whether a variable should be allocated on the heap or on the stack
● Creates a graph of function calls in order to track variables scope
● Uses tracking data to pass checks on those variables○ Those checks are not explicitly detailed in Go specs
● If checks pass, the variable is allocated on the stack (it doesn’t escape)
● If at least one check fails, the variable is allocated on the heap (it escapes)
● Escape analysis results can be checked at compile time using○ go build -gcflags '-m' ./main.go
![Page 29: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/29.jpg)
One basic rule (not always right…)
If a variable has its address taken,
that variable is a candidate for allocation on the heap
![Page 30: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/30.jpg)
Closure calls
Closure calls are not analyzed
![Page 31: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/31.jpg)
Assignments to slices and maps
A map can be allocated on the stack,
but any keys or values inserted into the map will escape
![Page 32: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/32.jpg)
Flow through channels
A variable passing through a channel
will always escape
![Page 33: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/33.jpg)
Interfaces
Interfaces can lead to escape
when a function of the given interface is called
(because the compiler doesn’t know
what the function is doing with its arguments)
![Page 34: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/34.jpg)
And a lot of other cases...
● Go escape analysis is very simple and not so smart
● Some issues are opened to improve it
![Page 35: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/35.jpg)
Conclusion
![Page 36: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/36.jpg)
Keep it simple, readable
● Avoid premature optimizations○ Sometimes, readability and logicalness are better than performances
● Use go tools in order to point out real problems○ pprof
○ gcflags
![Page 37: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/37.jpg)
Remember the basics
● Pointers are only useful if you directly manipulate variable value○ Most of the time, a copy of the value is sufficient
● Closures are not always sexy○ Do not overuse them just to overuse them
● Manipulate arrays when possible○ Slices are cool, but arrays too... :)
![Page 38: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/38.jpg)
Thank youfor listening!
![Page 39: Advanced memory allocation](https://reader030.fdocuments.in/reader030/viewer/2022021508/5a6487617f8b9a2c568b5409/html5/thumbnails/39.jpg)
References
● https://segment.com/blog/allocation-efficiency-in-high-performance-go-services/● https://en.wikipedia.org/wiki/Stack-based_memory_allocation● http://gribblelab.org/CBootCamp/7_Memory_Stack_vs_Heap.html● https://dave.cheney.net/2014/06/07/five-things-that-make-go-fast● https://blog.cloudflare.com/how-stacks-are-handled-in-go/● http://www.tldp.org/LDP/tlk/mm/memory.html● http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory/● http://agis.io/2014/03/25/contiguous-stacks-in-go.html● https://medium.com/@felipedutratine/does-golang-inline-functions-b41ee2d743fa● https://docs.google.com/document/d/1CxgUBPlx9iJzkz9JWkb6tIpTe5q32QDmz8l0BouG0Cw/preview