最近阅读了一下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