func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { ... if size <= maxSmallSize {... } else {var s *mspansystemstack(func() {s = largeAlloc(size, needzero, noscan)})s.freeindex = 1s.allocCount = 1x = unsafe.Pointer(s.base())size = s.elemsize } publicationBarrier() mp.mallocing = 0 releasem(mp) return x}runtime.largeAlloc 函数会计算分配该对象所需要的页数,它会按照 8KB 的倍数为对象在堆上申请内存:
func largeAlloc(size uintptr, needzero bool, noscan bool) *mspan { npages := size >> _PageShift if size&_PageMask != 0 {npages++ } ... s := mheap_.alloc(npages, makeSpanClass(0, noscan), needzero) s.limit = s.base() + size heapBitsForAddr(s.base()).initSpan(s) return s}申请内存时会创建一个跨度类为 0 的 runtime.spanClass 并调用 runtime.mheap.alloc 分配一个管理对应内存的管理单元 。
小结内存分配是 Go 语言运行时内存管理的核心逻辑,运行时的内存分配器使用类似 TCMalloc 的分配策略将对象根据大小分类,并设计多层级的组件提高内存分配器的性能 。本节不仅介绍了 Go 语言内存分配器的设计与实现原理,同时也介绍了内存分配器的常见设计,帮助我们理解不同编程语言在设计内存分配器时做出的不同选择 。
内存分配器虽然非常重要,但是它只解决了如何分配内存的问题,我们在本节中省略了很多与垃圾回收相关的代码,没有分析运行时垃圾回收的实现原理,在下一节中我们将详细分析 Go 语言垃圾回收的设计与实现原理 。
延伸阅读
- The Go Memory Model
- A visual guide to Go Memory Allocator from scratch (Golang)
- TCMalloc : Thread-Caching Malloc
- Getting to Go: The Journey of Go's Garbage Collecton
- Go: Memory Management and Allocation
推荐阅读
- 茶艺享受的是时间,茶艺根据不同的原则和方法的分类
- 茶油的营养价值,长期吃茶油的坏处
- 茶具的选购之配套用具,茶具的奇思妙想
- 科学管理Linux系统中的组与组成员
- 大红袍的产地,名茶大红袍的产地是哪
- svchost占用内存过高是怎么回事
- 基于MEC的边缘CDN业务调度方案及测试分析
- 茶香面包的做法,红茶面包棒的做法
- JavaScript的Array.flat函数深入探讨
- 买电脑、DIY电脑,你必须了解的避坑技能
