runtime 包

runtime 包 提供了運(yùn)行時與系統(tǒng)的交互,比如控制協(xié)程函數(shù)净宵,觸發(fā)垃圾立即回收等等底層操作,下面我們就運(yùn)行時能做的所有事情逐個進(jìn)行說明與代碼演示

  • 1.獲取GOROOT環(huán)境變量
  • 2.獲取GO的版本號
  • 3.獲取本機(jī)CPU個數(shù)
  • 4.設(shè)置最大可同時執(zhí)行的最大CPU數(shù)
  • 5.設(shè)置cup profile 記錄的速錄
  • 6.查看cup profile 下一次堆棧跟蹤數(shù)據(jù)
  • 7.立即執(zhí)行一次垃圾回收
  • 8.給變量綁定方法,當(dāng)垃圾回收的時候進(jìn)行監(jiān)聽
  • 9.查看內(nèi)存申請和分配統(tǒng)計(jì)信息
  • 10.查看程序正在使用的字節(jié)數(shù)
  • 11.查看程序正在使用的對象數(shù)
  • 12.獲取調(diào)用堆棧列表
  • 13.獲取內(nèi)存profile記錄歷史
  • 14.執(zhí)行一個斷點(diǎn)
  • 15.獲取程序調(diào)用go協(xié)程的棧蹤跡歷史
  • 16.獲取當(dāng)前函數(shù)或者上層函數(shù)的標(biāo)識號吐辙、文件名、調(diào)用方法在當(dāng)前文件中的行號
  • 17.獲取與當(dāng)前堆棧記錄相關(guān)鏈的調(diào)用棧蹤跡
  • 18.獲取一個標(biāo)識調(diào)用棧標(biāo)識符pc對應(yīng)的調(diào)用棧
  • 19.獲取調(diào)用棧所調(diào)用的函數(shù)的名字
  • 20.獲取調(diào)用棧所調(diào)用的函數(shù)的所在的源文件名和行號
  • 21.獲取該調(diào)用棧的調(diào)用棧標(biāo)識符
  • 22.獲取當(dāng)前進(jìn)程執(zhí)行的cgo調(diào)用次數(shù)
  • 23.獲取當(dāng)前存在的go協(xié)程數(shù)
  • 24.終止掉當(dāng)前的go協(xié)程
  • 25.讓其他go協(xié)程優(yōu)先執(zhí)行,等其他協(xié)程執(zhí)行完后,在執(zhí)行當(dāng)前的協(xié)程
  • 26.獲取活躍的go協(xié)程的堆棧profile以及記錄個數(shù)
  • 27.將調(diào)用的go協(xié)程綁定到當(dāng)前所在的操作系統(tǒng)線程击蹲,其它go協(xié)程不能進(jìn)入該線程
  • 28.解除go協(xié)程與操作系統(tǒng)線程的綁定關(guān)系
  • 29.獲取線程創(chuàng)建profile中的記錄個數(shù)
  • 30.控制阻塞profile記錄go協(xié)程阻塞事件的采樣率
  • 31.返回當(dāng)前阻塞profile中的記錄個數(shù)

1.獲取GOROOT環(huán)境變量

func GOROOT() string
GOROOT返回Go的根目錄。如果存在GOROOT環(huán)境變量项玛,返回該變量的值荞估;否則咳促,返回創(chuàng)建Go時的根目錄

package main
import (
    "fmt"
  "runtime"
)
func main() {
fmt.Println(runtime.GOROOT())
}

image.png
image.png

2.獲取GO的版本號

func Version() string
返回Go的版本字符串色难。它要么是遞交的hash和創(chuàng)建時的日期;要么是發(fā)行標(biāo)簽如"go1.3"

package main

import (
    "fmt"
  "runtime"
)

func main() {
fmt.Println(runtime.Version())
}

image.png
image.png

3.獲取本機(jī)CPU個數(shù)

func NumCPU() int
NumCPU返回本地機(jī)器的邏輯CPU個數(shù)

package main

import (
  "fmt"
  "runtime"
)

func main() {
fmt.Println(runtime.NumCPU())
}

image.png
image.png

4.設(shè)置最大可同時執(zhí)行的最大CPU數(shù)

func GOMAXPROCS(n int) int

GOMAXPROCS設(shè)置可同時執(zhí)行的最大CPU數(shù)等缀,并返回先前的設(shè)置枷莉。 若 n < 1,它就不會更改當(dāng)前設(shè)置尺迂。本地機(jī)器的邏輯CPU數(shù)可通過 NumCPU 查詢笤妙。本函數(shù)在調(diào)度程序優(yōu)化后會去掉

使用默認(rèn)的cup數(shù)量 我的電腦是4核的

package main

import (
  "fmt"
  "time"
  )
func main() {

   //runtime.GOMAXPROCS(1)
    startTime := time.Now()
    var s1 chan  int64 = make(chan int64)
    var s2 chan  int64 = make(chan int64)
    var s3 chan  int64 = make(chan int64)
    var s4 chan  int64 = make(chan int64)
    go calc(s1)
    go calc(s2)
    go calc(s3)
    go calc(s4)
    <-s1
    <-s2
    <-s3
    <-s4
    endTime := time.Now()
    fmt.Println(endTime.Sub(startTime))
    
}
func calc(s  chan int64) {
   var count int64 = 0
  for i := 0 ;i < 1000000000;i++ {
    count += int64(i)
  }
  s <- count
}
image.png
image.png

下面我們將cup數(shù)量設(shè)置成1

package main
import (
  "fmt"
  "time"
  "runtime"
)

func main() {
   runtime.GOMAXPROCS(1)
    startTime := time.Now()
    var s1 chan  int64 = make(chan int64)
    var s2 chan  int64 = make(chan int64)
    var s3 chan  int64 = make(chan int64)
    var s4 chan  int64 = make(chan int64)
    go calc(s1)
    go calc(s2)
    go calc(s3)
    go calc(s4)
    <-s1
    <-s2
    <-s3
    <-s4
    endTime := time.Now()
    fmt.Println(endTime.Sub(startTime))

}
func calc(s  chan int64) {
   var count int64 = 0
  for i := 0 ;i < 1000000000;i++ {
    count += int64(i)
  }
  s <- count
}
image.png
image.png

很明顯速度慢了很多

5.設(shè)置cup profile 記錄的速錄

func SetCPUProfileRate(hz int)
SetCPUProfileRate設(shè)置CPU profile記錄的速率為平均每秒hz次。如果hz<=0噪裕,SetCPUProfileRate會關(guān)閉profile的記錄蹲盘。如果記錄器在執(zhí)行,該速率必須在關(guān)閉之后才能修改膳音。

絕大多數(shù)使用者應(yīng)使用runtime/pprof包或testing包的-test.cpuprofile選項(xiàng)而非直接使用SetCPUProfileRate

6.查看cup profile 下一次堆棧跟蹤數(shù)據(jù)

func CPUProfile() []byte
目前已廢棄

7.立即執(zhí)行一次垃圾回收

func GC()
GC執(zhí)行一次垃圾回收

看一下代碼

package main

import (
   "runtime"
  "time"
)
type Student struct {
  name string

}
func main() {
  var i *Student = new(Student)
  runtime.SetFinalizer(i, func(i interface{}) {
   println("垃圾回收了")
  })
  runtime.GC()
  time.Sleep(time.Second)
}
image.png
image.png

我們創(chuàng)建了一個指針類型的變量Student 當(dāng)我們調(diào)用runtime.GC的時候,內(nèi)存立即會回收召衔,你可以把runtime.GC()屏蔽掉,程序就不在執(zhí)行了


8.給變量綁定方法,當(dāng)垃圾回收的時候進(jìn)行監(jiān)聽

func SetFinalizer(x, f interface{})

注意x必須是指針類型,f 函數(shù)的參數(shù)一定要和x保持一致,或者寫interface{},不然程序會報(bào)錯

示例如下

package main

import (
   "runtime"
  "time"
)
type Student struct {
  name string

}
func main() {
  var i *Student = new(Student)
  runtime.SetFinalizer(i, func(i *Student) {
   println("垃圾回收了")
  })
  runtime.GC()
  time.Sleep(time.Second)
}

image.png
image.png

9.查看內(nèi)存申請和分配統(tǒng)計(jì)信息

func ReadMemStats(m *MemStats)
我們可以獲得下面的信息

type MemStats struct {
    // 一般統(tǒng)計(jì)
    Alloc      uint64 // 已申請且仍在使用的字節(jié)數(shù)
    TotalAlloc uint64 // 已申請的總字節(jié)數(shù)(已釋放的部分也算在內(nèi))
    Sys        uint64 // 從系統(tǒng)中獲取的字節(jié)數(shù)(下面XxxSys之和)
    Lookups    uint64 // 指針查找的次數(shù)
    Mallocs    uint64 // 申請內(nèi)存的次數(shù)
    Frees      uint64 // 釋放內(nèi)存的次數(shù)
    // 主分配堆統(tǒng)計(jì)
    HeapAlloc    uint64 // 已申請且仍在使用的字節(jié)數(shù)
    HeapSys      uint64 // 從系統(tǒng)中獲取的字節(jié)數(shù)
    HeapIdle     uint64 // 閑置span中的字節(jié)數(shù)
    HeapInuse    uint64 // 非閑置span中的字節(jié)數(shù)
    HeapReleased uint64 // 釋放到系統(tǒng)的字節(jié)數(shù)
    HeapObjects  uint64 // 已分配對象的總個數(shù)
    // L低層次、大小固定的結(jié)構(gòu)體分配器統(tǒng)計(jì)祭陷,Inuse為正在使用的字節(jié)數(shù)苍凛,Sys為從系統(tǒng)獲取的字節(jié)數(shù)
    StackInuse  uint64 // 引導(dǎo)程序的堆棧
    StackSys    uint64
    MSpanInuse  uint64 // mspan結(jié)構(gòu)體
    MSpanSys    uint64
    MCacheInuse uint64 // mcache結(jié)構(gòu)體
    MCacheSys   uint64
    BuckHashSys uint64 // profile桶散列表
    GCSys       uint64 // GC元數(shù)據(jù)
    OtherSys    uint64 // 其他系統(tǒng)申請
    // 垃圾收集器統(tǒng)計(jì)
    NextGC       uint64 // 會在HeapAlloc字段到達(dá)該值(字節(jié)數(shù))時運(yùn)行下次GC
    LastGC       uint64 // 上次運(yùn)行的絕對時間(納秒)
    PauseTotalNs uint64
    PauseNs      [256]uint64 // 近期GC暫停時間的循環(huán)緩沖,最近一次在[(NumGC+255)%256]
    NumGC        uint32
    EnableGC     bool
    DebugGC      bool
    // 每次申請的字節(jié)數(shù)的統(tǒng)計(jì)兵志,61是C代碼中的尺寸分級數(shù)
    BySize [61]struct {
        Size    uint32
        Mallocs uint64
        Frees   uint64
    }
}
package main

import (
   "runtime"
  "time"
  "fmt"
)
type Student struct {
  name string

}
func main() {
  var list = make([]*Student,0)
  for i:=0;i <100000 ;i++ {
    var s *Student = new(Student)
    list = append(list, s)
  }
  memStatus := runtime.MemStats{}
  runtime.ReadMemStats(&memStatus)
  fmt.Printf("申請的內(nèi)存:%d\n",memStatus.Mallocs)
  fmt.Printf("釋放的內(nèi)存次數(shù):%d\n",memStatus.Frees)
  time.Sleep(time.Second)
}

image.png
image.png

10.查看程序正在使用的字節(jié)數(shù)

func (r *MemProfileRecord) InUseBytes() int64
InUseBytes返回正在使用的字節(jié)數(shù)(AllocBytes – FreeBytes)

11.查看程序正在使用的對象數(shù)

func (r *MemProfileRecord) InUseObjects() int64
InUseObjects返回正在使用的對象數(shù)(AllocObjects - FreeObjects)

12.獲取調(diào)用堆棧列表

func (r *MemProfileRecord) Stack() []uintptr
Stack返回關(guān)聯(lián)至此記錄的調(diào)用棧蹤跡醇蝴,即r.Stack0的前綴。

13.獲取內(nèi)存profile記錄歷史

func MemProfile(p []MemProfileRecord, inuseZero bool) (n int, ok bool)
MemProfile返回當(dāng)前內(nèi)存profile中的記錄數(shù)n想罕。若len(p)>=n悠栓,MemProfile會將此分析報(bào)告復(fù)制到p中并返回(n, true);如果len(p)<n按价,MemProfile則不會更改p惭适,而只返回(n, false)。

如果inuseZero為真楼镐,該profile就會包含無效分配記錄(其中r.AllocBytes>0癞志,而r.AllocBytes==r.FreeBytes。這些內(nèi)存都是被申請后又釋放回運(yùn)行時環(huán)境的)鸠蚪。

大多數(shù)調(diào)用者應(yīng)當(dāng)使用runtime/pprof包或testing包的-test.memprofile標(biāo)記今阳,而非直接調(diào)用MemProfile

14.執(zhí)行一個斷點(diǎn)

func Breakpoint()

runtime.Breakpoint()
image.png
image.png

15.獲取程序調(diào)用go協(xié)程的棧蹤跡歷史

func Stack(buf []byte, all bool) int
Stack將調(diào)用其的go程的調(diào)用棧蹤跡格式化后寫入到buf中并返回寫入的字節(jié)數(shù)师溅。若all為true茅信,函數(shù)會在寫入當(dāng)前go程的蹤跡信息后,將其它所有g(shù)o程的調(diào)用棧蹤跡都格式化寫入到buf中墓臭。

package main

import (
     "time"
  "runtime"
  "fmt"
)

func main() {
  go showRecord()
  time.Sleep(time.Second)
  buf := make([]byte,10000)
  runtime.Stack(buf,true)
  fmt.Println(string(buf))
}

func showRecord(){
 tiker := time.Tick(time.Second)
 for t := range  tiker {
   fmt.Println(t)
 }
}
image.png
image.png

我們在調(diào)用Stack方法后,首先格式化當(dāng)前go協(xié)程的信息蘸鲸,然后把其他正在運(yùn)行的go協(xié)程也格式化后寫入buf中

16.獲取當(dāng)前函數(shù)或者上層函數(shù)的標(biāo)識號、文件名窿锉、調(diào)用方法在當(dāng)前文件中的行號

func Caller(skip int) (pc uintptr, file string, line int, ok bool)

package main
import (
  "runtime"
  "fmt"
)

func main() {
  pc,file,line,ok := runtime.Caller(0)
  fmt.Println(pc)
  fmt.Println(file)
  fmt.Println(line)
  fmt.Println(ok)
}
image.png
image.png

pc = 17380971 不是main函數(shù)自己的標(biāo)識 runtime.Caller 方法的標(biāo)識,line = 13 標(biāo)識它在main方法中的第13行被調(diào)用

package main

import (
  "runtime"
  "fmt"
)

func main() {
  pc,_,line,_ := runtime.Caller(1)
  fmt.Printf("main函數(shù)的pc:%d\n",pc)
  fmt.Printf("main函數(shù)被調(diào)用的行數(shù):%d\n",line)
  show()
}
func show(){
  pc,_,line,_ := runtime.Caller(1)
  fmt.Printf("show函數(shù)的pc:%d\n",pc)
  fmt.Printf("show函數(shù)被調(diào)用的行數(shù):%d\n",line)
  // 這個是main函數(shù)的棧
  pc,_,line,_ = runtime.Caller(2)
  fmt.Printf("show的上層函數(shù)的pc:%d\n",pc)
  fmt.Printf("show的上層函數(shù)被調(diào)用的行數(shù):%d\n",line)
  pc,_,_,_ = runtime.Caller(3)
  fmt.Println(pc)
  pc,_,_,_ = runtime.Caller(4)
  fmt.Println(pc)
}
image.png
image.png

通過上面的例子我演示了如何追蹤一個方法被調(diào)用的順序,以及所有相關(guān)函數(shù)的信息

17.獲取與當(dāng)前堆棧記錄相關(guān)鏈的調(diào)用棧蹤跡

func Callers(skip int, pc []uintptr) int

函數(shù)把當(dāng)前go程調(diào)用棧上的調(diào)用棧標(biāo)識符填入切片pc中酌摇,返回寫入到pc中的項(xiàng)數(shù)膝舅。實(shí)參skip為開始在pc中記錄之前所要跳過的棧幀數(shù),0表示Callers自身的調(diào)用棧窑多,1表示Callers所在的調(diào)用棧仍稀。返回寫入p的項(xiàng)數(shù)

package main

import (
  "runtime"
  "fmt"
)


func main() {
  pcs := make([]uintptr,10)
  i := runtime.Callers(1,pcs)
  fmt.Println(pcs[:i])
}
image.png
image.png

我們獲得了三個pc 其中有一個是main方法自身的

18.獲取一個標(biāo)識調(diào)用棧標(biāo)識符pc對應(yīng)的調(diào)用棧

func FuncForPC(pc uintptr) *Func

package main

import (
  "runtime"
  )


func main() {

  pcs := make([]uintptr,10)
  i := runtime.Callers(1,pcs)
  for _,pc := range pcs[:i]{
    println(runtime.FuncForPC(pc))
  }
}
image.png
image.png

我們知道這個調(diào)用棧有什么用呢?請繼續(xù)下想看

19.獲取調(diào)用棧所調(diào)用的函數(shù)的名字

func (f *Func) Name() string

package main

import (
  "runtime"
  )



func main() {

  pcs := make([]uintptr,10)
  i := runtime.Callers(1,pcs)
  for _,pc := range pcs[:i]{
    funcPC := runtime.FuncForPC(pc)
    println(funcPC.Name())
  }
}
image.png
image.png

20.獲取調(diào)用棧所調(diào)用的函數(shù)的所在的源文件名和行號

func (f *Func) FileLine(pc uintptr) (file string, line int)

package main
import (
  "runtime"
  )

func main() {
  pcs := make([]uintptr,10)
  i := runtime.Callers(1,pcs)
  for _,pc := range pcs[:i]{
    funcPC := runtime.FuncForPC(pc)
    file,line := funcPC.FileLine(pc)
    println(funcPC.Name(),file,line)
  }
}
image.png
image.png

21.獲取該調(diào)用棧的調(diào)用棧標(biāo)識符

func (f *Func) Entry() uintptr

package main

import (
  "runtime"
  )



func main() {
  pcs := make([]uintptr,10)
  i := runtime.Callers(1,pcs)
  for _,pc := range pcs[:i]{
    funcPC := runtime.FuncForPC(pc)
    println(funcPC.Entry())
  }
}

image.png
image.png

22.獲取當(dāng)前進(jìn)程執(zhí)行的cgo調(diào)用次數(shù)

func NumCgoCall() int64
獲取當(dāng)前進(jìn)程調(diào)用c方法的次數(shù)
`

package main

import (
  "runtime"
  )
/*
#include <stdio.h>
*/
import "C"




func main() {
 println(runtime.NumCgoCall())
}

image.png
image.png

注意我們沒有調(diào)用c的方法為什么是1呢?因?yàn)?code>import c是,會調(diào)用了c包中的init方法

下面我們看一個完整例子

import (
  "runtime"
  )
/*
#include <stdio.h>
// 自定義一個c語言的方法
static void myPrint(const char* msg) {
  printf("myPrint: %s", msg);
}
*/
import "C"




func main() {
  // 調(diào)用c方法
  C.myPrint(C.CString("Hello,C\n"))
  println(runtime.NumCgoCall())
}
image.png
image.png

23.獲取當(dāng)前存在的go協(xié)程數(shù)

func NumGoroutine() int

package main

import "runtime"



func main() {
 go print()
 print()
 println(runtime.NumGoroutine())
}
func print(){

}

image.png
image.png

我們可以看到輸出的是2 表示存在2個go協(xié)程 一個是main.go 另外一個是go print()

24.終止掉當(dāng)前的go協(xié)程

func Goexit()

package main
import (
  "runtime"
    "fmt"
)

func main() {
 print()  // 1
 fmt.Println("繼續(xù)執(zhí)行")
}
func print(){
  fmt.Println("準(zhǔn)備結(jié)束go協(xié)程")
  runtime.Goexit()
  defer fmt.Println("結(jié)束了")
}

image.png
image.png

Goexit終止調(diào)用它的go協(xié)程,其他協(xié)程不受影響,Goexit會在終止該go協(xié)程前執(zhí)行所有的defer函數(shù)埂息,前提是defer必須在它前面定義,如果在main go協(xié)程調(diào)用本方法,會終止該go協(xié)程,但不會讓main返回,因?yàn)閙ain函數(shù)沒有返回,程序會繼續(xù)執(zhí)行其他go協(xié)程,當(dāng)其他go協(xié)程執(zhí)行完畢后,程序就會崩潰

25.讓其他go協(xié)程優(yōu)先執(zhí)行,等其他協(xié)程執(zhí)行完后,在執(zhí)行當(dāng)前的協(xié)程

func Gosched()

我們先看一個示例

package main
import (
  "fmt"
  )

func main() {
  go print()  // 1
  fmt.Println("繼續(xù)執(zhí)行")
}
func print(){
  fmt.Println("執(zhí)行打印方法")
}
image.png
image.png

我們在1處調(diào)用了go print方法,但是還未執(zhí)行 main函數(shù)就執(zhí)行完畢了,因?yàn)閮蓚€協(xié)程是并發(fā)的

那么我們應(yīng)該怎么才能讓每個協(xié)程都能夠執(zhí)行完畢呢?方法有很多種,不過就針對這個知識點(diǎn),我們就使用 runtime.Gosched()來解決

package main
import (
  "fmt"
  "runtime"
)

func main() {
  go print()  // 1
  runtime.Gosched()
  fmt.Println("繼續(xù)執(zhí)行")
}
func print(){
  fmt.Println("執(zhí)行打印方法")
}

image.png
image.png

26.獲取活躍的go協(xié)程的堆棧profile以及記錄個數(shù)

func GoroutineProfile(p []StackRecord) (n int, ok bool)


27.將調(diào)用的go協(xié)程綁定到當(dāng)前所在的操作系統(tǒng)線程技潘,其它go協(xié)程不能進(jìn)入該線程

func LockOSThread()
將調(diào)用的go程綁定到它當(dāng)前所在的操作系統(tǒng)線程。除非調(diào)用的go程退出或調(diào)用UnlockOSThread千康,否則它將總是在該線程中執(zhí)行享幽,而其它go程則不能進(jìn)入該線程

我們看下面一個例子

package main
import (
  "fmt"
  "runtime"
  "time"
)

func main() {
  go calcSum1()
  go calcSum2()
  time.Sleep(time.Second*100)
}

func calcSum1(){
  runtime.LockOSThread()
  start := time.Now()
  count := 0
  for i := 0; i < 10000000000 ; i++  {
    count += i
  }
  end := time.Now()
  fmt.Println("calcSum1耗時")
  fmt.Println(end.Sub(start))
  defer runtime.UnlockOSThread()
}

func calcSum2(){
  start := time.Now()
  count := 0
  for i := 0; i < 10000000000 ; i++  {
    count += i
  }
  end := time.Now()
  fmt.Println("calcSum2耗時")
  fmt.Println(end.Sub(start))
}
image.png
image.png

測試速度沒有多大的差別,如果有需要協(xié)程,但是有一項(xiàng)重要的功能需要占一個核,就需要

28.解除go協(xié)程與操作系統(tǒng)線程的綁定關(guān)系

func UnlockOSThread()
將調(diào)用的go程解除和它綁定的操作系統(tǒng)線程拾弃。若調(diào)用的go程未調(diào)用LockOSThread值桩,UnlockOSThread不做操作

29.獲取線程創(chuàng)建profile中的記錄個數(shù)

func ThreadCreateProfile(p []StackRecord) (n int, ok bool)
返回線程創(chuàng)建profile中的記錄個數(shù)。如果len(p)>=n豪椿,本函數(shù)就會將profile中的記錄復(fù)制到p中并返回(n, true)奔坟。若len(p)<n,則不會更改p搭盾,而只返回(n, false)蛀蜜。

絕大多數(shù)使用者應(yīng)當(dāng)使用runtime/pprof包,而非直接調(diào)用ThreadCreateProfile增蹭。

30.控制阻塞profile記錄go協(xié)程阻塞事件的采樣率

func SetBlockProfileRate(rate int)

SetBlockProfileRate控制阻塞profile記錄go程阻塞事件的采樣頻率滴某。對于一個阻塞事件,平均每阻塞rate納秒滋迈,阻塞profile記錄器就采集一份樣本霎奢。

要在profile中包括每一個阻塞事件,需傳入rate=1饼灿;要完全關(guān)閉阻塞profile的記錄幕侠,需傳入rate<=0。

31.返回當(dāng)前阻塞profile中的記錄個數(shù)

func BlockProfile(p []BlockProfileRecord) (n int, ok bool)

BlockProfile返回當(dāng)前阻塞profile中的記錄個數(shù)碍彭。如果len(p)>=n晤硕,本函數(shù)就會將此profile中的記錄復(fù)制到p中并返回(n, true)。如果len(p)<n庇忌,本函數(shù)則不會修改p舞箍,而只返回(n, false)。

絕大多數(shù)使用者應(yīng)當(dāng)使用runtime/pprof包或testing包的-test.blockprofile標(biāo)記皆疹, 而非直接調(diào)用 BlockProfile

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末疏橄,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌捎迫,老刑警劉巖晃酒,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異窄绒,居然都是意外死亡贝次,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進(jìn)店門彰导,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浊闪,“玉大人,你說我怎么就攤上這事螺戳「楸觯” “怎么了?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵倔幼,是天一觀的道長盖腿。 經(jīng)常有香客問我,道長损同,這世上最難降的妖魔是什么翩腐? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮膏燃,結(jié)果婚禮上茂卦,老公的妹妹穿的比我還像新娘。我一直安慰自己组哩,他們只是感情好等龙,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著伶贰,像睡著了一般蛛砰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上黍衙,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天泥畅,我揣著相機(jī)與錄音,去河邊找鬼琅翻。 笑死位仁,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的方椎。 我是一名探鬼主播聂抢,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼辩尊!你這毒婦竟也來了涛浙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤摄欲,失蹤者是張志新(化名)和其女友劉穎轿亮,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胸墙,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡我注,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了迟隅。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片但骨。...
    茶點(diǎn)故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖智袭,靈堂內(nèi)的尸體忽然破棺而出奔缠,到底是詐尸還是另有隱情,我是刑警寧澤吼野,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布校哎,位于F島的核電站,受9級特大地震影響瞳步,放射性物質(zhì)發(fā)生泄漏闷哆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一单起、第九天 我趴在偏房一處隱蔽的房頂上張望抱怔。 院中可真熱鬧,春花似錦嘀倒、人聲如沸屈留。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绕沈。三九已至,卻和暖如春帮寻,著一層夾襖步出監(jiān)牢的瞬間乍狐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工固逗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留浅蚪,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓烫罩,卻偏偏與公主長得像惜傲,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子贝攒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內(nèi)容