Garbage Collection
本文由tom原创,转载请注明原文链接:https://work-jlsun.github.io//2016/04/22/ProgrammingLanguages-GarbageCollection.html
前一整子研究了下golang的GC机制,然后顺藤摸瓜找了些基本的GC算法的资料,学习了下GC算法方面的内容。
推荐 The University of Texas at Austin 计算机系编程语言一课中的 《Garbage Collection》 一课的内容,叫兽就是教授,总结的真好。看看能不能翻译、整理、吸收下。
1 内存的分布
主要的几种内存的分布区域
- Static area
固定的大小,固定的内容,在编译的时候已经确定分配。
- Runtime stack
可变的大小,可变的内容(动态纪录);典型的场景为函数的调用链(局部变量)和返回。
- Heap
固定的大小,变化的内容;动态分配的objects和data structures; 比如malloc in C,new in Java。
2 Cells And LiveNess
Cell: 在heap中的数据单元;
Cells 由存在于各种存储区域中的指针所指向
- registers、stack中的指针
- global/static memory
- 其它的heap cells
Roots(根对象): registers、stack locations、global/static variables
一个cell是存活的当其仅当其指针存在于Root中或者由其它存活的cell间接指向。
3 Garbage
Garbage - 程序运行过程中产生的无法被访问到的heap memory 或者内存释放了但是在程序里头还有引用的heap memory。
An allocated block of heap memory does not have a reference to it (cell is no longer “live”)
Another kind of memory error: a reference exists to a block of memory that is no longer allocated
Garbage Collection - 自动管理动态申请的内存空间,即自动回收不再使用的head memory以便后续继续提供给程序使用。
|
|
3.1 Why Garbage Collection
为什么现代程序设计语言基本都选择具备垃圾回收机制?
如今的应用程序非常可以随意自由的进行内存分配
- 1GB laptop,1-4GB desktops, 8~512GB servers
- 64-bit address spaces
但是却没有很好的管理
- Memorey leaks, dangling references, double free, misaligned addresses, null pointer deference, heap fragmentation
- Poor use of refererce locality, resulting in highcache miss rates and/or excessive demand paging
显式的内存管理容易打破上层编程逻辑的抽象
3.2 The Perfect Garbage Collector
完美的垃圾回收应该具备如下特点
基本要求
- No visible impact on program execution
- Works with any program and its data structures
- For Eaxmple,handles cyclic data structures
进阶要求
- Collects garbage(and obly garbage) cells quickly
- Incremental; can meet real-time constraints
- Has excellent spatial locality of reference
- No excessive paging, no negative cache effects
- Manages the heap efficiently
- Always satisfies an allocation request and does not fragment
3.3 Summary of GC Techiques
基本的GC技术及其核心特点如下
- Reference counting
- 直接跟踪所有的live cell
- 不论是否在heap上分配内存,GC机制都会发生
- 不会发现所有的垃圾
- Tracing
- GC takes place and identyfies live cells when a request for memory fails
- Mark-sweep
- Copy collection
- Modern techniques: generational GC
以下详细介绍这几种常见GC算法和其优缺点。
4 Reference Counting
- 简单的实时统计每一个cell的引用计数
- 存储count 和 引用计数增减会造成 一定的space和time的开销
- Reference counts是实时维护的,所以没有 “stop-and-collect” 即停止程序进行垃圾回收的过程
- 一种天生的增量垃圾回收方式
- 典型应用场景:C++ “Smart pointer”
优点
- Incremental overhead(增量的开销)
- cell管理插入在程序的正常程序执行逻辑过程中
- 适合于对交互性或者实时计算型负载
- 实现比较简单
- 与手动内存管理可以共存
- Spatial locality of reference is good
- Access pattern to virtual memory pages no worse than the program, so no excessive paging
- 可以快速进行内存复用
- If RC == 0, put back onto the free list
缺点
- 空间开销
- 一个word用于计数、1 个字节的用于间接指针记录
时间开销
- 更新一个指针指向另外一个cell需要如下步骤
- 确保指针并不是自引用
- 在old cell上执行 count–;如果引用为0,则删除old cell
- 更新指针指向new cell的地址
- 对new cell 执行 count++
- 更新一个指针指向另外一个cell需要如下步骤
一次 miss的count(increment/decrement)操作会导致dangling pointer/memory leak
循环的数据结构可能会导致内存泄漏
Reference Count 典型实现 “Smart Poniter” in C++
优点分析如下:
- sizeof(RefObj
) = 8 bytes (8 bytes per reference-counted object) - sizeof(Ref
) = 4 bytes - Fits in a register
- Easily passed by value as an argument or result of a function
- Takes no more space than regular pointer but much “safer”
源码实现
|
|
智能指针的使用
|
|
5 Mark-Sweep Garbage Collection
- 每个cell有一个 mark bit
- Garbage 在heap 使用完之前都是unreachable、undetected的、GC在heap内存用尽之后触发执行,并且程序执行开始挂起(stop-the-world)
两个阶段
- Marking phase(“标记”):从所有root开始,标记所有live cell。
- Sweep phase(“清理”):将所有 “未标记”的cell 汇总到freelist循环使用;clear所有mark bit的标记位,等待下次gc重新标记。
mark-sweep 优缺点分析
优点
- 能够正确的处理 cycle
- 几乎没有空间开销
- 1 bit用于标记cell(may limit max values that can be stored in a cell, e.g.., for integer cells)
缺点
- 常规的执行必须被挂起(stop the world)
- may touch all virtual memory pages
- May lead to excessive paging if the working-set size is small and the heap is not all in physical memory.
- heap 可能会碎片化
- Cache misses, page thrashing; more complex allocation.
6 Copying Collector
- 将heap划分为 “from-space”以及”to-space”
from-space 中的cells是被trace的,在回收的时候将live cell (“scavenged”) 拷贝到 to-space
- 为了保证数据结构之间在回收后是正确指向的,必须更新所有原来在from-space中的cell对应的指针。
- PS:This is why references in Java and other languages are not pointers, but indirect abstractions for pointers
当to-space 使用完,两边space角色切换
cheneys 算法pesucode 如下
优点
- 相对较小的cell 分配开销
- 由于分配都是连续的,out-of-space 检测只需要一次addr比较
- 能够高效的allocate 可变大小的cell
- 没有内存碎片问题
缺点
- 两倍的内存开销
- Copy大对象(大内存拷贝)开销大
7 Generational Garbage Collection
- 观测到:大多数cell的生命周期都是很短的
- 将heap区分为多个区域,对生命周期短的cell进行更加频繁的GC
- 在 GC期间不需要扫描所有的cell
- 周期性得对“older generations” 进行GC
如下为“分代GC”的简单示例,将young GC阶段好久没有被垃圾回收的对象迁移到“older generation”。
以下分代GC机制结合Copying Collector的示例。
8 附录|参考
This article used CC-BY-SA-4.0 license, please follow it.