最近阅读了一下golang的runtime,其中一个文档干货很多,于是简要翻译了一下。
github的排版比较好看一些。
以下是翻译
-------------------------------------------------
这是一个简要的文档,以后可能会过时。 它意在说清楚go runtime和普通代码编写的不同。 它注重普适的概念而不是某个接口的细节
调度结构
调度器管理着遍布runtime的三种类型的资源:Gs,Ms 和Ps。 即使你不是从事调度器开发也应该理解这些结构。
Gs, Ms, Ps
gggg
m
pGOMAXPROCS
调度器的工作是使G(要执行的代码),M(在哪里执行),和P(执行的权利和资源)相协调。 当一个M在执行用户代码的时候停止了,比如进入系统调用, 他返回持有的P给闲置的P池 为了重新开始执行晕乎代码,例如从系统调用返回, 它(M)必须从空闲的P池中获取一个P
gmp
用户栈和系统栈
每个非死亡的G有一个相连的 用户栈 ,即用户代码在何处执行。 用户栈刚开始很小(比如,2k) 可以动态增长或下降。
每个M有一个相关的 系统栈 (即M的g0的栈),以及一个 信号栈 (即gsingal). 系统栈和信号栈不能增长,但是足够执行runtime的代码以及cgo代码 (在纯go二进制文件中是8k,在cgo中是系统分配)
systemstackmcallasmcgocall
getg()getg().m.curg
ggetg().m.curg
getg()g
getg() == getg().m.curg
错误处理和报告
panicpanicmallocgc
throwthorwthrowprintprintln
GOTRACEBACK=systemGOTRACEBACK=crash
同步
runtime有多个同步机制。他们有不同的语意, 尤其是,他们与goroutine调度器和系统调度器相互影响。
mutexlockunlockmutexrwmutex
notenotesleepnotewakeupsleepwakeupnotenotewakeupnotesleepnotenoteclearnotemutexnotenotesleepnotesleepg
goparkgoreadygopark
goready
简要概括
非托管内存
一般来说,runtime尝试使用普通的堆分配的内存。 然而,有些时候runtime必须使用不在gc堆上的内存,(即 unmanaged memeory) 如果对象是内存管理系统本身的一部分或者在某些调用者不含P的情况下分配的。 (即这部分内存不受gc控制,是更底层的接口,直接用mmap分配的)
分配非托管内存有三种方式
- sysAlloc 直接从OS获取内存。可以获取任何系统页大小(4k)整数倍的内存, 也可以被sysFree释放
- persistentalloc 吧多个小内存组合为单次sysAlloc防止内存碎片。 然而,没有办法释放其分配的内存。
- fixalloc 是slab风格的分配器,用于分配固定大小的对象。 fixalloc分配的对象可以被释放,但是这个内存可能会被fixalloc pool复用, 因此它只能给相同类型的对象复用。
//go:notinheap
非托管内存分配的对象 禁止 含有堆指针,除非一下满足以下条件:
runtime.markroot
Zero-initialization versus zeroing
runtime中有两种置零方式,取决于内存是否已经初始化为类型安全的状态
memclrNoHeapPointers
typedmemclrmemclrHasPointers
runtime-only 编译准则
除了"go doc compile" 中的"//go:"准则之外, 还有一些只能用于runtime的编译准则。
go:systemstack
go:systemstack
go:nowritebarrier
go:nowritebarrier
go:nowritebarruerrecgo:nowritebarrier
go:nowritebarrierrec and go:yeswritebarrierrec
go:nowritebarrierrecgo:yeswritebarrierrec
go:nowritebarrierrecgo:yeswritebarrierrec
go:nowritebarrierrec
getg().m.p !=nilgo:nowritebarrierrecgo:yeswritebarrierrec
因为他们是函数级别的注视,释放或获取P的代码可能需要分割为两个。
go:notinheap
go:notinheapruntime.inheap
new(T)make([]Y)append([]T, ...)unsafe.Pointergo:notinheapgo:notinheapgo:notinheapgo:notinheapgo:notinheapgo:notinheapgo:notinheap
go:notinheap