栈内存和堆内存
第一、计算机为什么需要内存?
(1)暂存二进制可执行代码文件中的指令、预置数据(常量)等
(2)暂存指令执行过程中的中间数据
第二、为什么需要栈内存?
通过利用「栈内存」,CPU在执行指令过程中可以高效地存储临时变量。是对一段连续内存的「线性分配」。
第三、为什么需要堆内存?
Go语言会在代码编译期间通过「逃逸分析」把分配在「栈」上的变量分配到「堆」上去。
第四、虚拟内存的引出?
(1)以32位计算机为例,寻址的范围是2^32也就是4G,如果每个进程都分配4G大小的内存,则会导致内存不足,后来的进程等待,之后再装入内存,这种频繁的装入内存的操作是很没效率的。
(2)由于指令都是直接访问物理内存的,那么我这个进程就可以修改其他进程的数据,甚至会修改内核地址空间的数据,这是我们不想看到的
(3)程序想要分配一段连续的内存空间时候,物理内存分配往往是不连续的内存碎片。
第五、go分配内存原理
因此一个go进程分配的是虚拟内存。
栈内存分配原则:
(1)小于32KB的栈内存。依次来源:mcache 线程缓存 -> stackpool 全局缓存 -> p.pagecache 逻辑处理器结构 -> mheap 堆
(2)大于等于32KB的栈内存。依次来源:stackpool全局缓存 -> p.pagecache 逻辑处理器结构 -> mheap 堆
堆内存分配原则:
(1)小于16B的堆内存。mcache.tiny 线程的微型分配器 -> mcache.alloc 线程缓存
(2)大于等于16B且小于等于32KB的堆内存。mcache.alloc 线程缓存 -> mcentral 中央缓存 -> p.pagecache逻辑处理器结构 -> mheap 堆
(3)大于32KB的堆内存。p.pagecache逻辑处理器结构 -> mheap 堆