一、包概述

1
import "runtime"
  • runtime包提供和go运行时环境的互操作,如控制go程的函数
  • 也包括用于reflect包的低层次类型信息。参见reflect报的文档获取运行时类型系统的可编程接口

二、相关环境变量

GOGC

  • 环境变量GOGC设置最初的垃圾收集目标百分比
  • 当新申请的数据和前次垃圾收集剩下的存活数据的比率达到该百分比时,就会触发垃圾收集
  • 默认GOGC=100
  • 设置GOGC=off会完全关闭垃圾收集
  • runtime/debug包的SetGCPercent函数允许在运行时修改该百分比。参见http://golang.org/pkg/runtime/debug/#SetGCPercent

GODEBUG

  • 环境变量GODEBUG控制运行时的debug输出。GODEBUG的值是逗号分隔的name=val对
  • 支持的name如下:
    • allocfreetrace:设置其为1,会导致每次分配都会被记录剖面,会记录每一个对象的分配、释放及其堆栈踪迹
    • efence:设置其为1,会导致分配器运行模式为:每个对象申请在独立的页和地址,且永不循环利用
    • gctrace:设置其为1,会导致垃圾收集器每次收集都向标准错误输出写入单行的数据,概述收集的总内存的大小和暂停的总时间长度。设置其为2,会写入同样的概述,但也会写入每次收集的两个数据
    • gcdead:设置其为1,会导致垃圾收集器摧毁任何它认为已经死掉的执行堆栈
    • schedtrace:设置其为X,会导致调度程序每隔X毫秒输出单行信息到标准错误输出,概述调度状态
    • scheddetail:设置schedtrace为X并设置其为1,会导致调度程序每隔X毫秒输出详细的多行信息,描述调度、进程、线程和go程的状态

GOMAXPROCS

  • 环境变量GOMAXPROCS限制可以同时运行用户层次的go代码的操作系统进程数
  • 没有对代表go代码的、可以在系统调用中阻塞的go程数的限制;那些阻塞的go程不与GOMAXPROCS限制冲突。本包的GOMAXPROCS函数可以查询和修改该限制

GOTRACEBACK

  • 环境变量GOTRACEBACK控制当go程序因为不能恢复的panic或不期望的运行时情况失败时的输出
  • 失败的程序默认会打印所有现存go程的堆栈踪迹(省略运行时系统中的函数),然后以状态码2退出。如果GOTRACEBACK为0,会完全忽略所有go程的堆栈踪迹。如果GOTRACEBACK为1,会采用默认行为。如果GOTRACEBACK为2,会打印所有现存go程包括运行时函数的堆栈踪迹。如果GOTRACEBACK为crash,会打印所有现存go程包括运行时函数的堆栈踪迹,并且如果可能会采用操作系统特定的方式崩溃,而不是退出。例如,在Unix系统里,程序会释放SIGABRT信号以触发核心信息转储

其他环境变量

  • 环境变量GOARCH、GOOS、GOPATH和GOROOT构成完整的go环境变量集合。它们影响go程序的构建(参见http://golang.org/pkg/go/build和http://golang.org/cmd/go)
  • GOARCH、GOOS和GOROOT在编译时被记录并可用本包的常量和函数获取,但它们不会影响运行时环境

三、包总览

常量

1
2
3
4
5
const Compiler = "gc"

const GOARCH string = theGoarch

const GOOS string = theGoos

变量

1
var MemProfileRate int = 512 * 1024

类型、接口与函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
type Error

type TypeAssertionError
func (e *TypeAssertionError) Error() string
func (*TypeAssertionError) RuntimeError()

func GOROOT() string
func Version() string
func NumCPU() int
func GOMAXPROCS(n int) int
func GC()
func SetFinalizer(x, f interface{})

type MemStats
func ReadMemStats(m *MemStats)

type MemProfileRecord
func (r *MemProfileRecord) InUseBytes() int64
func (r *MemProfileRecord) InUseObjects() int64
func (r *MemProfileRecord) Stack() []uintptr

func MemProfile(p []MemProfileRecord, inuseZero bool) (n int, ok bool)
func SetCPUProfileRate(hz int)
func CPUProfile() []byte
func Breakpoint()
func Stack(buf []byte, all bool) int
func Caller(skip int) (pc uintptr, file string, line int, ok bool)
func Callers(skip int, pc []uintptr) int

type StackRecord
func (r *StackRecord) Stack() []uintptr

type Func
func FuncForPC(pc uintptr) *Func
func (f *Func) Entry() uintptr
func (f *Func) FileLine(pc uintptr) (file string, line int)
func (f *Func) Name() string

func NumCgoCall() int64
func NumGoroutine() int
func Goexit()
func Gosched()
func GoroutineProfile(p []StackRecord) (n int, ok bool)
func LockOSThread()
func UnlockOSThread()
func ThreadCreateProfile(p []StackRecord) (n int, ok bool)
type BlockProfileRecord
func SetBlockProfileRate(rate int)
func BlockProfile(p []BlockProfileRecord) (n int, ok bool)

四、常量

Compiler

1
const Compiler = "gc"
  • Compiler是编译工具链的名字,工具链会构建可执行的二进制文件
  • 已知的工具链是:
1
2
gc      The 5g/6g/8g compiler suite at code.google.com/p/go.
gccgo   The gccgo front end, part of the GCC compiler suite.

GOARCH

1
const GOARCH string = theGoarch
  • GOARCH是可执行程序的目标处理器架构(将要在该架构的机器上执行):386、amd64或arm。

GOOS

1
const GOOS string = theGoos
  • GOOS是可执行程序的目标操作系统(将要在该操作系统的机器上执行):darwin、freebsd、linux等

五、变量

MemProfileRate

1
var MemProfileRate int = 512 * 1024
  • MemProfileRate控制会在内存profile里记录和报告的内存分配采样频率。内存profile记录器平均每分配MemProfileRate字节进行一次分配采样。
  • 要在profile里包含每一个申请的块,可以将MemProfileRate设为1。要完全关闭profile的记录,设置本变量为0
  • 处理内存profile的工具假设profile记录速度在整个程序的生命期是固定的,并等于当前值。修改内存profile的程序应该只进行一次,且尽可能早的修改(例如,在main函数的开始处)

六、错误处理

type Error

1
2
3
4
5
6
type Error interface {
    error
    // RuntimeError是一个无操作的函数,仅用于区别运行时错误和普通错误。
    // 具有RuntimeError方法的错误类型就是运行时错误类型。
    RuntimeError()
}
  • Error接口用来识别运行时错误

type TypeAssertionError

1
2
3
type TypeAssertionError struct {
    // 内含隐藏或非导出字段
}
  • TypeAssertionError表示一次失败的类型断言
  • Error():
1
func (e *TypeAssertionError) Error() string
  • RuntimeError():
1
func (*TypeAssertionError) RuntimeError()

七、相关函数

func GOROOT()

1
func GOROOT() string
  • GOROOT返回Go的根目录
  • 如果存在GOROOT环境变量,返回该变量的值;否则,返回创建Go时的根目录

func Version()

1
func Version() string
  • 返回Go的版本字符串。它要么是递交的hash和创建时的日期;要么是发行标签如"go1.3"

func NumCPU()

1
func NumCPU() int
  • NumCPU返回本地机器的逻辑CPU个数

func GOMAXPROCS()

1
func GOMAXPROCS(n int) int
  • GOMAXPROCS设置可同时执行的最大CPU数,并返回先前的设置
  • 若 n < 1,它就不会更改当前设置。本地机器的逻辑CPU数可通过 NumCPU 查询。本函数在调度程序优化后会去掉

func SetCPUProfileRate()

1
func SetCPUProfileRate(hz int)
  • SetCPUProfileRate设置CPU profile记录的速率为平均每秒hz次。如果hz<=0,SetCPUProfileRate会关闭profile的记录。如果记录器在执行,该速率必须在关闭之后才能修改
  • 绝大多数使用者应使用runtime/pprof包或testing包的-test.cpuprofile选项而非直接使用SetCPUProfileRate

func CPUProfile()

1
func CPUProfile() []byte
  • CPUProfile返回二进制CPU profile堆栈跟踪数据的下一个chunk,函数会阻塞直到该数据可用
  • 如果profile的记录被关闭,且在记录器开着的时候积累的profile数据都被返回了,CPUProfile会返回nil。调用者在再次调用本函数之前应先保存返回的数据
  • 绝大多数使用者应使用 runtime/pprof包或testing包的-test.cpuprofile选项而非直接使用 CPUProfile

func GC()

1
func GC()
  • GC执行一次垃圾回收

func SetFinalizer()

1
func SetFinalizer(x, f interface{})
  • SetFinalizer将x的终止器设置为f。当垃圾收集器发现一个不能接触的(即引用计数为零,程序中不能再直接或间接访问该对象)具有终止器的块时,它会清理该关联(对象到终止器)并在独立go程调用f(x)。这使x再次可以接触,但没有了绑定的终止器。如果SetFinalizer没有被再次调用,下一次垃圾收集器将视x为不可接触的,并释放x
  • SetFinalizer(x, nil)会清理任何绑定到x的终止器
  • 参数x必须是一个指向通过new申请的对象的指针,或者通过对复合字面值取址得到的指针。参数f必须是一个函数,它接受单个可以直接用x类型值赋值的参数,也可以有任意个被忽略的返回值。如果这两条任一条不被满足,本函数就会中断程序
  • 终止器会按依赖顺序执行:如果A指向B,两者都有终止器,且它们无法从其它方面接触,只有A的终止器执行;A被释放后,B的终止器就可以执行。如果一个循环结构包含一个具有终止器的块,该循环不能保证会被当垃圾收集,终止器也不能保证会执行;因为没有尊重依赖关系的顺序
  • x的终止器会在x变为不可接触之后的任意时间被调度执行。不保证终止器会在程序退出前执行,因此一般终止器只用于在长期运行的程序中释放关联到某对象的非内存资源。例如,当一个程序丢弃一个os.File对象时没有调用其Close方法,该os.File对象可以使用终止器去关闭对应的操作系统文件描述符。但依靠终止器去刷新内存中的I/O缓冲如bufio.Writer是错误的,因为缓冲不会在程序退出时被刷新
  • 如果*x的大小为0字节,不保证终止器会执行
  • 一个程序会有单独一个go程顺序执行所有的终止器。如果一个终止器必须运行较长时间,它应该在内部另开go程执行该任务

八、type MemStats

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
type MemStats struct {
    // 一般统计
    Alloc      uint64 // 已申请且仍在使用的字节数
    TotalAlloc uint64 // 已申请的总字节数(已释放的部分也算在内)
    Sys        uint64 // 从系统中获取的字节数(下面XxxSys之和)
    Lookups    uint64 // 指针查找的次数
    Mallocs    uint64 // 申请内存的次数
    Frees      uint64 // 释放内存的次数
    // 主分配堆统计
    HeapAlloc    uint64 // 已申请且仍在使用的字节数
    HeapSys      uint64 // 从系统中获取的字节数
    HeapIdle     uint64 // 闲置span中的字节数
    HeapInuse    uint64 // 非闲置span中的字节数
    HeapReleased uint64 // 释放到系统的字节数
    HeapObjects  uint64 // 已分配对象的总个数
    // L低层次、大小固定的结构体分配器统计,Inuse为正在使用的字节数,Sys为从系统获取的字节数
    StackInuse  uint64 // 引导程序的堆栈
    StackSys    uint64
    MSpanInuse  uint64 // mspan结构体
    MSpanSys    uint64
    MCacheInuse uint64 // mcache结构体
    MCacheSys   uint64
    BuckHashSys uint64 // profile桶散列表
    GCSys       uint64 // GC元数据
    OtherSys    uint64 // 其他系统申请
    // 垃圾收集器统计
    NextGC       uint64 // 会在HeapAlloc字段到达该值(字节数)时运行下次GC
    LastGC       uint64 // 上次运行的绝对时间(纳秒)
    PauseTotalNs uint64
    PauseNs      [256]uint64 // 近期GC暂停时间的循环缓冲,最近一次在[(NumGC+255)%256]
    NumGC        uint32
    EnableGC     bool
    DebugGC      bool
    // 每次申请的字节数的统计,61是C代码中的尺寸分级数
    BySize [61]struct {
        Size    uint32
        Mallocs uint64
        Frees   uint64
    }
}
  • MemStats记录内存申请和分配的统计信息

func ReadMemStats()

1
func ReadMemStats(m *MemStats)
  • ReadMemStats将内存申请和分配的统计信息填写进m

九、type MemProfileRecord

1
2
3
4
5
type MemProfileRecord struct {
    AllocBytes, FreeBytes     int64       // 申请和释放的字节数
    AllocObjects, FreeObjects int64       // 申请和释放的对象数
    Stack0                    [32]uintptr // 该记录的调用栈踪迹,以第一个零值成员截止
}
  • MemProfileRecord用于描述某个调用栈序列申请和释放的活动对象等信息

func (r *MemProfileRecord) InUseBytes()

1
func (r *MemProfileRecord) InUseBytes() int64
  • InUseBytes返回正在使用的字节数(AllocBytes – FreeBytes)

func (r *MemProfileRecord) InUseObjects()

1
func (r *MemProfileRecord) InUseObjects() int64
  • InUseObjects返回正在使用的对象数(AllocObjects - FreeObjects)

func (r *MemProfileRecord) Stack()

1
func (r *MemProfileRecord) Stack() []uintptr
  • Stack返回关联至此记录的调用栈踪迹,即r.Stack0的前缀

func MemProfile()

1
func MemProfile(p []MemProfileRecord, inuseZero bool) (n int, ok bool)
  • MemProfile返回当前内存profile中的记录数n。若len(p)>=n,MemProfile会将此分析报告复制到p中并返回(n, true);如果len(p)
  • 如果inuseZero为真,该profile就会包含无效分配记录(其中r.AllocBytes>0,而r.AllocBytes==r.FreeBytes。这些内存都是被申请后又释放回运行时环境的)。
  • 大多数调用者应当使用runtime/pprof包或testing包的-test.memprofile标记,而非直接调用MemProfile。

func Breakpoint()

1
func Breakpoint()
  • Breakpoint执行一个断点陷阱

func Stack()

1
func Stack(buf []byte, all bool) int
  • Stack将调用其的go程的调用栈踪迹格式化后写入到buf中并返回写入的字节数。若all为true,函数会在写入当前go程的踪迹信息后,将其它所有go程的调用栈踪迹都格式化写入到buf中

func Caller()

1
func Caller(skip int) (pc uintptr, file string, line int, ok bool)
  • Caller报告当前go程调用栈所执行的函数的文件和行号信息。实参skip为上溯的栈帧数,0表示Caller的调用者(Caller所在的调用栈)。(由于历史原因,skip的意思在Caller和Callers中并不相同。)函数的返回值为调用栈标识符、文件名、该调用在文件中的行号。如果无法获得信息,ok会被设为false

func Callers()

1
func Callers(skip int, pc []uintptr) int
  • 函数把当前go程调用栈上的调用栈标识符填入切片pc中,返回写入到pc中的项数
  • 实参skip为开始在pc中记录之前所要跳过的栈帧数,0表示Callers自身的调用栈,1表示Callers所在的调用栈。返回写入p的项数

十、type StackRecord

1
2
3
type StackRecord struct {
    Stack0 [32]uintptr // 该记录的调用栈踪迹,以第一个零值成员截止
}
  • tackRecord描述单条调用栈

func (r *StackRecord) Stack()

1
func (r *StackRecord) Stack() []uintptr
  • Stack返回与记录相关联的调用栈踪迹,即r.Stack0的前缀

十一、type Func

1
2
3
type Func struct {
    // 内含隐藏或非导出字段
}

func FuncForPC()

1
func FuncForPC(pc uintptr) *Func
  • FuncForPC返回一个表示调用栈标识符pc对应的调用栈的*Func
  • 如果该调用栈标识符没有对应的调用栈,函数会返回nil。每一个调用栈必然是对某个函数的调用

func (f *Func) Name()

1
func (f *Func) Name() string
  • Name返回该调用栈所调用的函数的名字

func (f *Func) FileLine()

1
func (f *Func) FileLine(pc uintptr) (file string, line int)
  • FileLine返回该调用栈所调用的函数的源代码文件名和行号
  • 如果pc不是f内的调用栈标识符,结果是不精确的

func (f *Func) Entry()

1
func (f *Func) Entry() uintptr
  • Entry返回该调用栈的调用栈标识符

十二、其他函数

func NumCgoCall()

1
func NumCgoCall() int64
  • NumCgoCall返回当前进程执行的cgo调用次数

func NumGoroutine()

1
func NumGoroutine() int
  • NumGoroutine返回当前存在的Go程数

func Goexit()

1
func Goexit()
  • Goexit终止调用它的go程。其它go程不会受影响。Goexit会在终止该go程前执行所有defer的函数。
  • 在程序的main go程调用本函数,会终结该go程,而不会让main返回。因为main函数没有返回,程序会继续执行其它的go程。如果所有其它go程都退出了,程序就会崩溃。

func Gosched()

1
func Gosched()
  • Gosched使当前go程放弃处理器,以让其它go程运行。它不会挂起当前go程,因此当前go程未来会恢复执行

func GoroutineProfile()

1
func GoroutineProfile(p []StackRecord) (n int, ok bool)
  • GoroutineProfile返回活跃go程的堆栈profile中的记录个数。若len(p) >= n,函数就会将profile中的记录复制到p中并返回(n, true)。若len(p) < n,则不会修改p,而只返回(n, false)。
  • 绝大多数调用者应当使用runtime/pprof包,而非直接调用GoroutineProfile。

func LockOSThread()

1
func LockOSThread()
  • Entry返回该调用栈的调用栈标识符

func UnlockOSThread()

1
func UnlockOSThread()
  • 将调用的go程解除和它绑定的操作系统线程
  • 若调用的go程未调用LockOSThread,UnlockOSThread不做操作

func ThreadCreateProfile()

1
func ThreadCreateProfile(p []StackRecord) (n int, ok bool)
  • 返回线程创建profile中的记录个数。如果len(p)>=n,本函数就会将profile中的记录复制到p中并返回(n, true)。若len(p)
  • 绝大多数使用者应当使用runtime/pprof包,而非直接调用ThreadCreateProfile

十三、type BlockProfileRecord

1
2
3
4
5
type BlockProfileRecord struct {
    Count  int64
    Cycles int64
    StackRecord
}
  • BlockProfileRecord用于描述某个调用栈序列发生的阻塞事件的信息

func SetBlockProfileRate()

1
func SetBlockProfileRate(rate int)
  • SetBlockProfileRate控制阻塞profile记录go程阻塞事件的采样频率。对于一个阻塞事件,平均每阻塞rate纳秒,阻塞profile记录器就采集一份样本。
  • 要在profile中包括每一个阻塞事件,需传入rate=1;要完全关闭阻塞profile的记录,需传入rate<=0。

func BlockProfile()

1
func BlockProfile(p []BlockProfileRecord) (n int, ok bool)
  • BlockProfile返回当前阻塞profile中的记录个数。如果len(p)>=n,本函数就会将此profile中的记录复制到p中并返回(n, true)。如果len(p)
  • 绝大多数使用者应当使用runtime/pprof包或testing包的-test.blockprofile标记, 而非直接调用 BlockProfile。