- 全局常量与变量
- 方法
- Func">type Func
- Frame">type Frame
- Frames">type Frames
- MemStats">type MemStats
- BlockProfileRecord">type BlockProfileRecord
- StackRecord">type StackRecord
- MemProfileRecord">type MemProfileRecord
全局常量与变量
const GOOS string = theGoos 返回当前的操作系统
const GOARCH string = theGoarch 返回当前处理器架构
//内存profile记录器平均每分配MemProfileRate字节进行一次分配采样
var MemProfileRate int = 512 * 1024
方法
func GOROOT() string GOROOT返回Go的根目录
func Version() string 返回Go的版本字符串
func NumCPU() int 返回本地机器的逻辑CPU个数
func GOMAXPROCS(n int) int 设置cpu执行数,默认为本机cpu数。当参数小于 1 时使用默认值
func GC() 执行一次垃圾回收
// 类似析构函数的意思,将x的终止器设置为f,在x被垃圾回收时调用f
func SetFinalizer(x, f interface{})
参数x必须是指针类型。
参数f是一个函数,其参数就是x,并且没有返回值。
当GC发现x不可达时,会在另一个独立的goroutine中执行f(x)。
接着,GC会清除x的关联函数f。这样,x再次可达,但是没了关联函数。
当下次GC发现obj不可达时,会释放obj。
SetFinalizer只有在对象object被GC时,才会被执行。
其他情况下,都不会被执行,即使程序正常结束或者发生错误。
x的终止器会在x变为不可接触之后的任意时间被调度,不保证在程序退出之前执行
package main
import (
"log"
"runtime"
"time"
)
type Road int
func findRoad(r *Road) {
log.Println("road:", *r)
}
func entry(){
var rd Road = Road(999)
r := &rd
runtime.SetFinalizer(r, findRoad)
}
func main(){
entry()
for i:=0; i < 10; i++ {
time.Sleep(time.Second)
runtime.GC()
}
}
// 2019/02/07 17:27:07 road: 999
// KeepAlive将其参数标记为当前可达。这确保在程序中调用KeepAlive的点之前,不释放对象,也不运行它的finalizer
func KeepAlive(x interface{})
type File struct { d int }
d, err := syscall.Open("/file/path", syscall.O_RDONLY, 0)
// ... do something if err != nil ...
p := &File{d}
runtime.SetFinalizer(p, func(p *File) { syscall.Close(p.d) })
var buf [10]byte
n, err := syscall.Read(p.d, buf[:])
// Ensure p is not finalized until Read returns.
runtime.KeepAlive(p)
// No more uses of p after this point.
//Stack将调用其的go程的调用栈踪迹格式化后写入到buf中并返回写入的字节数
//若all为true,函数会在写入当前go程的踪迹信息后,将其它所有go程的调用栈踪迹都格式化写入到buf中
func Stack(buf []byte, all bool) int
//Caller报告当前go程调用栈所执行的函数的文件和行号信息
//实参skip为上溯的栈帧数,0表示Caller的调用者(Caller所在的调用栈)
//函数的返回值为调用栈标识符、文件名、该调用在文件中的行号
//如果无法获得信息,ok会被设为false
func Caller(skip int) (pc uintptr, file string, line int, ok bool)
package main
import (
"fmt"
"runtime"
)
func a() {
_, file, line, _ := runtime.Caller(0)
fmt.Println(file, line)
}
func b() {
}
func main() {
a()
}
/Users/mac/Desktop/go/commons/gintest/1.go 9
//函数把当前go程调用栈上的调用栈标识符填入切片pc中,返回写入到pc中的项数。
//实参skip为开始在pc中记录之前所要跳过的栈帧数,0表示Callers自身的调用栈(即最后一层是Callers所在的调用栈)。
func Callers(skip int, pc []uintptr) int
func fun() {
var a = make([]uintptr, 10)
fmt.Println(runtime.Callers(0, a)) // 5
}
func main() {
fun()
}
func NumCgoCall() int64 返回当前进程执行的cgo调用次数
func NumGoroutine() int 返回当前存在的Go程数
func Goexit() 退出当前 goroutine(但是defer语句会照常执行)
func Gosched() 让当前线程让出 cpu 以让其它线程运行,当前线程未来会继续执行
func LockOSThread() 将当前的go程绑定到当前所在的操作系统线程,其它go程则不能进入该线程
func UnlockOSThread() 线程解锁,如果没有绑定,不做任何操作
单核测试
func init() {
runtime.GOMAXPROCS(1) //使用单核
}
func main() {
exit := make(chan int)
go func() {
defer close(exit)
go func() {
fmt.Println("b")
}()
}()
for i := 0; i < 4; i++ {
fmt.Println("a:", i)
if i == 1 {
runtime.Gosched() //切换任务
}
}
<-exit
}
//由于是单核模式,是并发的模式,其他协程只有等main让出cpu后才能运行
a: 0
a: 1
b
a: 2
a: 3
多核测试
func main() {
exit := make(chan int)
go func() {
defer close(exit)
go func() {
fmt.Println("b")
}()
}()
for i := 0; i < 4; i++ {
fmt.Println("a:", i)
if i == 1 {
runtime.Gosched() //切换任务
}
}
<-exit
}
//会发现运行几次结果会存在不一样的问题
//因为设置了多核,此时的任务是并行状态,不需要main让出cpu,其他的协程就可以运行
a: 0
b
a: 1
a: 2
a: 3
type Func
type Func struct {
// 内含隐藏或非导出字段
}
//FuncForPC返回一个表示调用栈标识符pc对应的调用栈的*Func
//如果该调用栈标识符没有对应的调用栈,函数会返回nil
func FuncForPC(pc uintptr) *Func
func (f *Func) Name() string 返回该调用栈所调用的函数的名字
//FileLine返回该调用栈所调用的函数的源代码文件名和行号
//如果pc不是f内的调用栈标识符,结果是不精确的
func (f *Func) FileLine(pc uintptr) (file string, line int)
func (f *Func) Entry() uintptr Entry返回该调用栈的调用栈标识符
type Frame
Frame是由Frames为每个调用帧返回的信息
type Frame struct {
// PC是这个帧中位置的程序计数器。对于调用另一帧的帧,这将是调用指令的程序计数器。
// 由于内联,多个帧可能具有相同的PC值,但不同的符号信息。
PC uintptr
// Func是这个调用帧的Func值
Func *Func
// Function == Func.Name().
Function string
// 文件名和行号
File string
Line int
// Entry point program counter for the function; may be zero
// if not known. If Func is not nil then Entry ==
// Func.Entry().
Entry uintptr
// contains filtered or unexported fields
}
type Frames
type Frames struct {
// contains filtered or unexported fields
}
func CallersFrames(callers []uintptr) *Frames
func (ci *Frames) Next() (frame Frame, more bool)
package main
import (
"fmt"
"runtime"
"strings"
)
func main() {
c := func() {
// Ask runtime.Callers for up to 10 pcs, including runtime.Callers itself.
pc := make([]uintptr, 10)
n := runtime.Callers(0, pc)
if n == 0 {
// No pcs available. Stop now.
// This can happen if the first argument to runtime.Callers is large.
return
}
pc = pc[:n] // pass only valid pcs to runtime.CallersFrames
frames := runtime.CallersFrames(pc)
// Loop to get frames.
// A fixed number of pcs can expand to an indefinite number of Frames.
for {
frame, more := frames.Next()
// To keep this example's output stable
// even if there are changes in the testing package,
// stop unwinding when we leave package runtime.
if !strings.Contains(frame.File, "runtime/") {
break
}
fmt.Printf("- more:%v | %s\n", more, frame.Function)
if !more {
break
}
}
}
b := func() { c() }
a := func() { b() }
a()
}
type MemStats
MemStats记录内存申请和分配的统计信息。
type MemStats struct {
// 已分配堆对象的字节数,同下面的HeapAlloc
Alloc uint64
// 为堆对象分配的累积字节数,一直增加,对象被释放也不会减少
TotalAlloc uint64
// 从系统中获取的字节数(下面XxxSys之和)
Sys uint64
// 指针查找的次数
Lookups uint64
// 申请内存的次数
Mallocs uint64
// 释放内存的次数
Frees uint64
// 已分配堆对象的字节数
// 包含所有可达,以及被GC标记为不可达但还没被清理的对象
HeapAlloc uint64
// 从系统中获取的字节数
HeapSys uint64
// 闲置span中的字节数
HeapIdle uint64
// 非闲置span中的字节数
HeapInuse uint64
// 释放到系统的字节数
HeapReleased uint64
// 已分配对象的总个数
HeapObjects uint64
// mspan 在使用的字节数
MSpanInuse uint64
// mspan 从系统中获得的字节数
MSpanSys uint64
// mcache 在使用的字节数
MCacheInuse uint64
// mcache 从系统中获得的字节数
MCacheSys uint64
// profile桶散列表
BuckHashSys uint64
// 垃圾收集元数据中的内存字节数
GCSys uint64 // Go 1.2
OtherSys uint64 // Go 1.2
// 会在HeapAlloc字段到达该值(字节数)时运行下次GC
NextGC uint64
// 上次运行的绝对时间(纳秒)
LastGC uint64
// 由于GC 导致的STW总耗时(纳秒)
PauseTotalNs uint64
// 近期GC暂停时间的循环缓冲,最近一次在[(NumGC+255)%256]
PauseNs [256]uint64
// GC 开始时间循环缓冲,最近一次在[(NumGC+255)%256] = LastGC
PauseEnd [256]uint64 // Go 1.4
NumGC uint32
NumForcedGC uint32 // Go 1.8
GCCPUFraction float64 // Go 1.5
EnableGC bool
DebugGC bool
BySize [61]struct {
// Size is the maximum byte size of an object in this
// size class.
Size uint32
// Mallocs is the cumulative count of heap objects
// allocated in this size class. The cumulative bytes
// of allocation is Size*Mallocs. The number of live
// objects in this size class is Mallocs - Frees.
Mallocs uint64
// Frees is the cumulative count of heap objects freed
// in this size class.
Frees uint64
}
}
func ReadMemStats(m *MemStats)
type BlockProfileRecord
BlockProfileRecord用于描述某个调用栈序列发生的阻塞事件的信息
type BlockProfileRecord struct {
Count int64
Cycles int64
StackRecord
}
//SetBlockProfileRate控制阻塞profile记录go程阻塞事件的采样频率。
//对于一个阻塞事件,平均每阻塞rate纳秒,阻塞profile记录器就采集一份样本。
//要在profile中包括每一个阻塞事件,需传入rate=1;要完全关闭阻塞profile的记录,需传入rate<=0。
func SetBlockProfileRate(rate int)
//BlockProfile返回当前阻塞profile中的记录个数。
//如果len(p)>=n,本函数就会将此profile中的记录复制到p中并返回(n, true)。
//如果len(p)<n,本函数则不会修改p,而只返回(n, false)。
//使用者应当使用runtime/pprof包或testing包的-test.blockprofile标记,而非直接调用 BlockProfile。
func BlockProfile(p []BlockProfileRecord) (n int, ok bool)
//MutexProfile 返回n,当前互斥锁配置文件中的记录数。
//如果len(p) >= n, MutexProfile将该配置文件复制到p中,并返回n, true。
//否则,MutexProfile不会更改p,并返回n, false
//使用者应当使用runtime/pprof包,而不是直接调用MutexProfile
func MutexProfile(p []BlockProfileRecord) (n int, ok bool)
func SetMutexProfileFraction(rate int) int
func SetBlockProfileRate(rate int)
type StackRecord
StackRecord描述单条调用栈
type StackRecord struct {
Stack0 [32]uintptr // 该记录的调用栈踪迹,以第一个零值成员截止
}
// Stack返回与记录相关联的调用栈踪迹
func (r *StackRecord) Stack() []uintptr
//GoroutineProfile返回活跃go程的堆栈profile中的记录个数。
//若len(p) >= n,函数就会将profile中的记录复制到p中并返回(n, true)。
//若len(p) < n,则不会修改p,而只返回(n, false)。
//绝大多数调用者应当使用runtime/pprof包,而非直接调用GoroutineProfile。
func GoroutineProfile(p []StackRecord) (n int, ok bool)
//返回线程创建profile中的记录个数。
//如果len(p)>=n,本函数就会将profile中的记录复制到p中并返回(n, true)。
//若len(p)<n,则不会更改p,而只返回(n, false)。
//绝大多数使用者应当使用runtime/pprof包,而非直接调用ThreadCreateProfile。
func ThreadCreateProfile(p []StackRecord) (n int, ok bool)
type MemProfileRecord
memprofilerrecord描述了由特定的调用序列(堆栈跟踪)分配的活动对象
type MemProfileRecord struct {
AllocBytes, FreeBytes int64 // number of bytes allocated, freed
AllocObjects, FreeObjects int64 // number of objects allocated, freed
Stack0 [32]uintptr // stack trace for this record; ends at first 0 entry
}
func (r *MemProfileRecord) InUseBytes() int64 AllocBytes - FreeBytes
func (r *MemProfileRecord) InUseObjects() int64 AllocObjects - FreeObjects
func (r *MemProfileRecord) Stack() []uintptr Stack返回与该记录关联的堆栈跟踪
//MemProfile返回每个分配站点分配和释放的内存的概要。
//MemProfile返回当前内存配置文件中的记录数n。
//如果len(p) >= n, MemProfile将该配置文件复制到p中,并返回n, true。
//如果len(p) < n, MemProfile不改变p并返回n, false。
//如果inuseZero为真,配置文件中包含r.AllocBytes > 0 但是r.AllocBytes == r.FreeBytes的分配记录。
//这些站点分配了内存,但是内存都被释放回运行时。
//绝大多数使用者应当使用runtime/pprof包,或-test.memprofile标记,而非直接调用MemProfile
func MemProfile(p []MemProfileRecord, inuseZero bool) (n int, ok bool)