runtime

主要组成部分:
- 内存管理
-
内存分配
- 使用TCMalloc(thread-cacheing malloc)算法的变体
- 对象根据大小分为微小对象(0-16B)、小对象(16B-32KB)和大对象(>32KB)。 使用 mspan 结构管理内存页,mcache 为每个 P 提供本地缓存。 内存分配时,会优先从 线程缓存 获取,当 线程缓存 没有足够的内存时,会尝试从 中心缓存 获取,如果申请内存超过 32KB 时,会直接从 页堆 获取。
- mcentral 用于在不同 mcache 之间平衡内存。
-
栈管理
- 使用分段栈(Segmented Stacks)技术,初始栈大小通常为 2KB。
- 当栈空间不足时,会触发栈扩容,创建新的更大的栈并复制内容。
- Go 1.4 之后采用连续栈(Contiguous Stacks)来避免 "hot split" 问题。
-
调度器
-
GMP 模型
- G(Goroutine):表示一个并发任务。
- M(Machine):表示操作系统线程。
- P(Processor):表示调度上下文,用于调度 G 到 M 上执行。 通常情况下,P 的数量等于 GOMAXPROCS。
-
工作窃取(Work Stealing)算法:
- 当一个 P 的本地队列为空时,会尝试从其他 P 的队列偷取任务。
- 保证负载均衡,提高整体性能。
-
调度过程:
-
当 G 被创建或变为可运行状态时,会被放入 P 的本地队列或全局队列。
-
M 会从绑定的 P 获取 G 来执行。
-
如果 G 执行系统调用,M 会与 P 解绑,其他 M 可能会接管该 P。
-
-
垃圾回收
-
三色标记清除算法:
-
白色:潜在的垃圾对象。
-
灰色:已被标记但其引用还未被扫描的对象。
-
黑色:已被标记且其所有引用都已被扫描的对象。
-
写屏障:
- 用于在并发标记过程中确保对象不会被错误地回收。
- 包括插入写屏障和删除写屏障。
-
-
并发标记和清除:
- GC 过程大部分与用户程序并发执行,仅在某些阶段会短暂 STW(Stop The World)。
-
触发机制:
- 基于堆大小、分配速率和时间间隔等因素自动触发。
-
系统调用
- a. 系统调用包装:
- Go runtime 对操作系统的系统调用进行了封装。
- 在进行系统调用时,会解绑 M 和 P,允许其他 G 在该 P 上运行。
-