// runtime/pprof/pprof.go
// 开启CPU采样,并设置频率
func StartCPUProfile(w io.Writer) error {
cpu.profiling = true
runtime.SetCPUProfileRate(hz)
go profileWriter(w)
}
// runtime/proc.go
// 处理 SIGPROF 信号
func sigprof(pc, sp, lr uintptr, gp *g, mp *m) {
// traceback,收集栈调用信息到 stk 切片里
// 从栈里可以解析出当前执行的函数、函数调用链等
n = gentraceback(pc, sp, lr, gp, 0, &stk[0], len(stk), nil, nil, _TraceTrap|_TraceJumpStack)
if prof.hz != 0 {
cpuprof.add(gp, stk[:n])
}
}
// 记录采样到 buffer
func (p *cpuProfile) add(gp *g, stk []uintptr) {
cpuprof.log.write(tagPtr, nanotime(), hdr[:], stk)
}
// runtime/pprof/pprof.go
// 循环调用 readProfile(),读取采样数据,并写入到指定的 cpu.prof 文件中
func profileWriter(w io.Writer) {
for { // 死循环
time.Sleep(100 * time.Millisecond) // 每100ms写一次,这个是写死的
data, tags, eof := readProfile()
if e := b.addCPUData(data, tags); e != nil && err == nil {
err = e
}
}
}
// runtime/malloc.go
func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
if rate := MemProfileRate; rate > 0 {
mp := acquirem()
profilealloc(mp, x, size) // 这里采样
releasem(mp)
}
}