DevilKing's blog

冷灯看剑,剑上几分功名?炉香无需计苍生,纵一穿烟逝,万丈云埋,孤阳还照古陵

0%

Go Memory Management

原文链接

Virtual Memory Size(VSZ) is all memory that the process can access, including memory that is swapped out, memory that is allocated, but not used, and memory that is from shared libraries. (Edited, good explanation in stackoverflow.)

Resident Set Size(RSS) is number of memory pages the process has in real memory multiplied by pagesize. This excludes swapped out memory pages.

一则

Go 通过 汇编或者 cgo 来调用这些系统调用,而不是 libc,所以它不提供 malloc, 而是直接向 OS 通过 mmap 要内存。Go 使用类似 TCMalloc: Thread-Caching Malloc 的方法管理内存。它比 libc malloc 更快效率更高,做法是使用 thread-local cache 存储预分配的内存对象。具体来说,给对象做大小分级,每个级别的管理都不太一样

golang内存模型

内存模型的目的是为了定义清楚变量的读写在不同执行体里的可见性。理解内存模型在并发编程中非常重要,因为代码的执行顺序和书写的逻辑顺序并不会完全一致,甚至在编译期间编译器也有可能重排代码以最优化CPU执行, 另外还因为有CPU缓存的存在,内存的数据不一定会及时更新,这样对内存中的同一个变量读和写也不一定和期望一样。

Go的并发模型是基于CSP(Communicating Sequential Process)的,不同的Goroutine通过一种叫Channel的数据结构来通信;Java的并发模型则基于多线程和共享内存,有较多的概念(violatie, lock, final, construct, thread, atomic等)和场景,当然java.util.concurrent并发工具包大大简化了Java并发编程

Happens-before 定义

Happens-before用来指明Go程序里的内存操作的局部顺序。如果一个内存操作事件e1 happens-before e2,则e2 happens-after e1也成立;如果e1不是happens-before e2,也不是happens-after e2,则e1和e2是并发的。

垃圾回收的时机

垃圾回收的触发是由一个gcpercent的变量控制的,当新分配的内存占已在使用中的内存的比例超过gcprecent时就会触发。比如,gcpercent=100,当前使用了4M的内存,那么当内存分配到达8M时就会再次gc。如果回收完毕后,内存的使用量为5M,那么下次回收的时机则是内存分配达到10M的时候。也就是说,并不是内存分配越多,垃圾回收频率越高,这个算法使得垃圾回收的频率比较稳定,适合应用的场景。

gcpercent的值是通过环境变量GOGC获取的,如果不设置这个环境变量,默认值是100。如果将它设置成off,则是关闭垃圾回收。