思考🤔
GO内存管理吸取当前内存多种管理方式优点,尤其是TCMalloc模型,在效率和GC方面已经足够优秀,作为工程师学习它是必要的。在学习过程中,我在想内存管理的产生是随着计算机发展而产生的,所以我想如果回到学习的原点,即没有内存的话,就不需要管理,换句话说为什么需要内存🤔,或者现代是否已经发展到可以不依赖内存而运行的阶段?
从图中看出,CPU寄存器存储速度快价格高,磁盘存储器速度慢价格低,但总是需要持久化存储数据的介质,所以磁盘是不能被淘汰的。假设CPU直连磁盘协同工作会导致CPU非常空闲,CPU如此昂贵空闲意味着资源浪费成本上升,所以会想法设法榨干CPU。所以有没有一种介质介于CPU和DISK之间可以对冲速率差,BINGO, 内存。
内存分配基于物理内存
进程是操作系统执行的基本单位,需要为其分配内存。内存分配是需要锁竞争。
内存分配基于虚拟内存
内存虚拟化和多线程技术的出现,每个进程都有各自的虚拟内存空间,空间大小可以远超物理内存。内存分配粒度可以降维到进程内,由进程内的线程对进程的内存锁竞争
进程内存
- text: 代码区
- data: 无论是静态变量还是全局变量
- stack: 栈区 从高地址向低地址增长 内存管理简单操作SP指针 容量小分配快
- heap: 堆区 从低地址向高地址增长 内存需要自身管理
堆区分配是比较头疼的问题,内存碎片,OOM…
内存分配需要锁竞争,高性能程序频繁分配内存是硬伤,有没有高效的分配方式🤔
GO内存
GO程序是多线程程序,为了使线程内存分配高效,尽可能无锁,让每个线程都有各自的一块内存。
可以参看这篇博文,写的很好。
核心思路就是将对象分配,每个线程维护一块Cache,尽可能使用Cache,不够时再向全局申请(锁),整体使锁的使用频率降低,提高效率。
GO逃逸分析
-
Sharing down typically stays on the stack
在调用方创建的变量或对象,通过参数的形式传递给被调用函数,这时在调用方创建的内存空间通常在栈上。这种在调用方创建内存,在被调用方使用该内存的“内存共享”方式,称之为 Sharing down。 -
Sharing up typically escapes to the heap
在被调用函数内创建的对象,以指针的形式返回给调用方的情况下,通常,创建的内存空间在堆上。这种在被调用方创建,在调用方使用的“内存共享”方式,称之为 Sharing up。 -
Only the compiler knows
之所以上面两条原则都加了通常,因为具体的分配方式,是由编译器确定的,一些编译器后端优化,可能会突破这两个原则,因此,具体的分配逻辑,只有编译器开发工程师知道
GOGC
可以参看这篇博文,写的很好