æ§è½ä¼ÂÃ¥ÂÂ建议
ç®Âä»Âï¼Â
- æ§è½ä¼ÂÃ¥ÂÂçÂÂÃ¥ÂÂæÂÂæ¯满足æ£确å¯é ãÂÂç®Âæ´Â渠æ°çÂÂè´¨éÂÂå ç´Â
- æ§è½ä¼ÂÃ¥ÂÂæ¯综åÂÂè¯Âä¼°ï¼ÂæÂÂæ¶åÂÂæ¶é´æÂÂçÂÂÃ¥ÂÂ空é´æÂÂçÂÂå¯è½对ç«Â
- éÂÂ对Goè¯Âè¨Âç¹æ§ï¼Âä»Âç»ÂGoç¸堳çÂÂæ§è½ä¼ÂÃ¥ÂÂ建议
BenchmarkçÂÂ使ç¨
æ§è½表ç°éÂÂè¦Âå®Âé æ°æ®衡éÂÂï¼ÂGoè¯Âè¨ÂæÂÂä¾ÂäºÂæ¯æÂÂåºåÂÂæ§è½æµÂè¯ÂçÂÂbenchmark工堷ãÂÂ
示ä¾Âï¼Â
//fib.go
package main
func Fib(n int) int {
if n < 2 {
return n
}
return Fib(n-1) + Fib(n-2)
}
//fib_test.go
package main
import (
"testing"
)
func BenchmarkFib10(b *testing.B) {
for i := 0; i < b.N; i++ {
Fib(10)
}
}
- benchmark Ã¥ÂÂæ®éÂÂçÂÂÃ¥ÂÂÃ¥Â
ÂæµÂè¯Âç¨ä¾Âä¸Âæ ·ï¼Âé½ä½ÂäºÂ
_test.go
æÂÂ件ä¸Âã - å½æ°åÂÂ以
Benchmark
å¼Â头ï¼ÂÃ¥ÂÂæ°æ¯b *testing.B
ãÂÂÃ¥ÂÂæ®éÂÂçÂÂÃ¥ÂÂå ÂæµÂè¯Âç¨ä¾Âå¾ÂÃ¥ÂÂï¼ÂÃ¥ÂÂå ÂæµÂè¯Âå½æ°åÂÂ以Test
å¼Â头ï¼ÂÃ¥ÂÂæ°æ¯t *testing.T
ãÂÂ
è¿Âè¡Â示ä¾Âï¼Â
- è¿Âè¡Âå½Âå package Ã¥ÂÂ
çÂÂç¨ä¾Âï¼Â
go test .
- è¿Âè¡Âå package Ã¥ÂÂ
çÂÂç¨ä¾Âï¼Â
go test ./<package name>
- å¦ÂæÂÂæ³éÂÂå½ÂæµÂè¯Âå½ÂÃ¥ÂÂç®å½Âä¸ÂçÂÂæÂÂæÂÂç packageï¼Â
go test ./...
go test
å½令é»Â认ä¸Âè¿Âè¡ benchmark ç¨ä¾ÂçÂÂï¼Âå¦ÂæÂÂæÂÂ们æ³è¿Âè¡ benchmark ç¨ä¾Âï¼ÂéÂÂè¦Âå 丠-bench
Ã¥ÂÂæ°ãÂÂä¾Âå¦Âï¼Â
$ go test -bench .
goos: windows
goarch: amd64
pkg: GoProject1
cpu: 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz
BenchmarkFib10-16 5496252 212.5 ns/op
PASS
ok GoProject1 1.454s
goos: windows
ï¼Âè¿Âè¡Âæ¾示è¿Âè¡ÂåºåÂÂæµÂè¯ÂçÂÂæÂÂä½Âç³»ç»Âï¼Âæ¤å¤Â为 WindowsãÂÂgoarch: amd64
ï¼Âè¿Âè¡Âæ¾示è¿Âè¡ÂåºåÂÂæµÂè¯ÂçÂÂæºå¨æ¶æÂÂï¼Âæ¤å¤Â为 64 ä½ AMD æ¶æÂÂãÂÂpkg: GoProject1
ï¼Âè¿Âè¡Âæ¾示å å«åºåÂÂæµÂè¯Â代ç ÂçÂÂå åÂÂï¼Âæ¤å¤Â为 “GoProject1″ãÂÂcpu: 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz
ï¼Âè¿Âè¡Âæ¾示è¿Âè¡ÂåºåÂÂæµÂè¯ÂçÂÂæºå¨ CPU ä¿¡æ¯ï¼Âå æ¬ CPU Ã¥ÂÂå·åÂÂæ¶éÂÂé¢ÂçÂÂãÂÂPASS
ï¼Âè¿Âè¡Â表示æÂÂæÂÂçÂÂæµÂè¯Âï¼Âå æμåÂÂæµÂè¯Âï¼Âé½已æÂÂÃ¥ÂÂéÂÂè¿ÂãÂÂok GoProject1 1.454s
ï¼Âè¿Âè¡Âæ¾示æÂÂæÂÂæµÂè¯Âï¼Âå æμåÂÂæµÂè¯Âï¼ÂçÂÂæ´ä½Âæ§è¡Âæ¶é´ãÂÂå¨è¿Âç§Âæ åµä¸Âï¼Âæ´个æµÂè¯Âå¥Â件æ§è¡Âæ¶é´大约为 1.454 ç§ÂãÂÂ
BenchmarkFib10-16
æ¯æµÂè¯Âå½æ°åÂÂï¼Â-16
表示GOMAXPROCS
çÂÂå¼为16ï¼ÂGOMAXPROCS 1.5
çÂÂæÂŒÂÂï¼Âé»Â认å¼为CPU
æ ¸æ° ãÂÂ5496252
表示ä¸ÂÃ¥Â
±æ§è¡Â5496252
次ï¼Âå³b.N
çÂÂå¼ãÂÂ212.5 ns/op
表示æ¯Â次æ§è¡Âè±费212.5ns
ãÂÂ
sliceä¼ÂÃ¥ÂÂ
é¢ÂÃ¥ÂÂé Âå åÂÂ
æÂ¥ä¸ÂæÂ¥çÂÂ两个å½æ°ï¼Â
func NoPreAlloc(size int) {
data := make([]int, 0)
for k := 0; k < size; k++ {
data = append(data, k)
}
}
func PreAlloc(size int) {
data := make([]int, 0, size)
for k := 0; k < size; k++ {
data = append(data, k)
}
}
Ã¥ÂÂå«为å®Â们ç¼ÂÃ¥ÂÂåºåÂÂæµÂè¯Âï¼Â
func BenchmarkNoPreAlloc(b *testing.B) {
for i := 0; i < b.N; i++ {
NoPreAlloc(1000000)
}
}
func BenchmarkPreAlloc(b *testing.B) {
for i := 0; i < b.N; i++ {
PreAlloc(1000000)
}
}
è¿Âè¡Âç»ÂæÂÂå¦Âä¸Âï¼Â
$ go test -bench .
goos: windows
goarch: amd64
pkg: GoProject1
cpu: 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz
BenchmarkNoPreAlloc-16 193 5968006 ns/op
BenchmarkPreAlloc-16 1498 825965 ns/op
PASS
ok GoProject1 3.164s
å¯以çÂÂå°é¢ÂÃ¥ÂÂé Âå åÂÂÃ¥ÂÂï¼Âæ§è½æ´好ãÂÂå æ¤åºÂå°½å¯è½å¨使ç¨make()Ã¥ÂÂå§ÂÃ¥ÂÂÃ¥ÂÂçÂÂæ¶æÂÂä¾Â容éÂÂä¿¡æ¯ãÂÂ
大å åÂÂæªéÂÂæ¾
å½ÂæÂÂ们å¨已æÂÂÃ¥ÂÂçÂÂåºç¡Âä¸ÂÃ¥ÂÂ建æ°çÂÂÃ¥ÂÂçÂÂæ¶ï¼Âæ°åÂÂçÂÂ并ä¸Âä¼ÂÃ¥ÂÂ建ä¸Â个æ°çÂÂåºÂå±Âæ°ç»ÂãÂÂç¸åÂÂï¼Âå®Âä¼Â報享åÂÂä¸Â个åºÂå±Âæ°ç»ÂãÂÂè¿Âç§Âæ åµä¸Âï¼Âå¦ÂæÂÂæÂÂ们ä»Âä¸Â个大åÂÂçÂÂä¸ÂæªåÂÂåºä¸Â个å°ÂÃ¥ÂÂçÂÂï¼Â并ä¸Âå¨代ç Âä¸Âä¿ÂçÂÂ对大åÂÂçÂÂçÂÂå¼Âç¨ï¼Âé£ä¹ÂÃ¥ÂÂåºÂå±Âæ°ç»Âå°Âä¼Âä¸Âç´åÂÂå¨äºÂå åÂÂä¸Âï¼Âå¾Âä¸Âå°éÂÂæ¾ï¼Âå³使大åÂÂçÂÂçÂÂå 容对æÂÂ们æ¥说已ç»Âä¸ÂÃ¥ÂÂéÂÂè¦ÂäºÂãÂÂ
举ä¾Â说æÂÂï¼ åÂÂ设æÂÂä¸Â个åÂÂ为bigSlice
çÂÂ大åÂÂçÂÂï¼ÂÃ¥Â
¶åºÂå±Âæ°ç»ÂéÂÂ常大ãÂÂç¶åÂÂæÂÂ们åºäºÂbigSlice
Ã¥ÂÂ建ä¸Â个æ°çÂÂå°ÂÃ¥ÂÂçÂÂsmallSlice
ï¼Â并ä¸Âå¨代ç Âä¸Âä¿ÂçÂÂ对bigSlice
çÂÂå¼Âç¨ãÂÂè¿Âæ ·ä¸ÂæÂ¥ï¼Âå³使æÂÂ们åª使ç¨smallSlice
ï¼ÂåºÂå±Âæ°ç»Âä¹Âä¸Âä¼Â被éÂÂæ¾ï¼Â导è´å ç¨大éÂÂçÂÂÃ¥ÂÂ
Ã¥ÂÂãÂÂ
ä¼ÂÃ¥ÂÂ建议ï¼Â使ç¨copyæ¿代re-slice 为äºÂé¿å Âä¸Âè¿°é·é±ï¼ÂæÂÂ们å¯以使ç¨copyæÂÂä½ÂæÂ¥åÂÂ建ä¸Â个æ°çÂÂÃ¥ÂÂçÂÂï¼ÂèÂÂä¸Âæ¯å¨已æÂÂÃ¥ÂÂçÂÂåºç¡Âä¸Â使ç¨re-sliceãÂÂcopyæÂÂä½Âä¼Âå°ÂæºÂÃ¥ÂÂçÂÂçÂÂå 容å¤Âå¶å°ä¸Â个æ°çÂÂåºÂå±Âæ°ç»Âä¸Âï¼Âè¿Âæ ·å°±ä¸Âä¼ÂÃ¥ÂÂÃ¥ÂÂå§ÂÃ¥ÂÂçÂÂ報享åºÂå±Âæ°ç»Âï¼Âé¿å ÂäºÂåºÂå±Âæ°ç»Âæ æ³ÂéÂÂæ¾çÂÂé®é¢ÂãÂÂ
示ä¾Â代ç Âï¼Â
goCopy codebigSlice := make([]int, 1000000) // Ã¥ÂÂ设bigSliceæ¯ä¸Â个éÂÂ常大çÂÂÃ¥ÂÂçÂÂ
// 使ç¨re-sliceï¼ÂsmallSliceÃ¥ÂÂbigSliceÃ¥Â
±äº«åÂÂä¸Â个åºÂå±Âæ°ç»Â
smallSlice := bigSlice[:100]
// 使ç¨copyï¼ÂÃ¥ÂÂ建ä¸Â个æ°çÂÂÃ¥ÂÂçÂÂï¼ÂåºÂå±Âæ°ç»Âå¾Âå°éÂÂæ¾
smallSlice = make([]int, 100)
copy(smallSlice, bigSlice[:100])
éÂÂè¿Â使ç¨copyæÂÂä½Âï¼ÂæÂÂ们å¯以é¿å Âå 为åºÂå±Âæ°ç»Âæ æ³ÂéÂÂæ¾èÂÂ导è´çÂÂå åÂÂ浪费é®é¢ÂãÂÂ
mapä¼ÂÃ¥ÂÂ
示ä¾Â代ç Âï¼Â
func NoPreAlloc(size int) {
data := make(map[int]int)
for k := 0; k < size; k++ {
data[k] = 1
}
}
func PreAlloc(size int) {
data := make(map[int]int, size)
for k := 0; k < size; k++ {
data[k] = 1
}
}
func BenchmarkNoPreAlloc(b *testing.B) {
for n := 0; n < b.N; n++ {
NoPreAlloc(1000000)
}
}
func BenchmarkPreAlloc(b *testing.B) {
for n := 0; n < b.N; n++ {
PreAlloc(1000000)
}
}
è¿Âè¡ÂæµÂè¯Âï¼Â
$ go test -bench .
goos: windows
goarch: amd64
pkg: GoProject1
cpu: 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz
BenchmarkNoPreAlloc-16 12 90044942 ns/op
BenchmarkPreAlloc-16 26 50461700 ns/op
PASS
ok GoProject1 2.637s
å¯以åÂÂç°mapé¢ÂÃ¥ÂÂé Âå åÂÂÃ¥ÂÂæÂÂæÂÂæ´好ãÂÂ
Ã¥ÂÂæÂÂï¼Â
- ä¸ÂæÂÂÃ¥ÂÂmapä¸Âæ·»å å Âç´ çÂÂæÂÂä½Âä¼Â触åÂÂmapçÂÂæ©容
- æÂÂÃ¥ÂÂÃ¥ÂÂé Â好空é´å¯以åÂÂå°Âå åÂÂæ·è´ÂÃ¥ÂÂRehashçÂÂæ¶ÂèÂÂãÂÂ
- 建议根æ®å®Âé éÂÂæ±ÂæÂÂÃ¥ÂÂé¢Â估好éÂÂè¦ÂçÂÂ空é´
Ã¥ÂÂ符串å¤ÂçÂÂä¼ÂÃ¥ÂÂ
使ç¨strings.Builder
ãÂÂé¢ÂÃ¥ÂÂéÂ
ÂÃ¥ÂÂ
Ã¥ÂÂãÂÂ
示ä¾Â代ç Âï¼Â
func Plus(n int, str string) string {
s := ""
for i := 0; i < n; i++ {
s += str
}
return s
}
func StrBuilder(n int, str string) string {
var builder strings.Builder
for i := 0; i < n; i++ {
builder.WriteString(str)
}
return builder.String()
}
func ByteBuffer(n int, str string) string {
buf := new(bytes.Buffer)
for i := 0; i < n; i++ {
buf.WriteString(str)
}
return buf.String()
}
func PreStrBuilder(n int, str string) string {
var builder strings.Builder
builder.Grow(n * len(str))
for i := 0; i < n; i++ {
builder.WriteString(str)
}
return builder.String()
}
func PreStrByteBuffer(n int, str string) string {
buf := new(bytes.Buffer)
buf.Grow(n * len(str))
for i := 0; i < n; i++ {
buf.WriteString(str)
}
return buf.String()
}
func BenchmarkPlus(b *testing.B) {
for i := 0; i < b.N; i++ {
Plus(100000, "wxy")
}
}
func BenchmarkStrBuilder(b *testing.B) {
for i := 0; i < b.N; i++ {
StrBuilder(100000, "wxy")
}
}
func BenchmarkByteBuffer(b *testing.B) {
for i := 0; i < b.N; i++ {
ByteBuffer(100000, "wxy")
}
}
func BenchmarkPreStrBuilder(b *testing.B) {
for i := 0; i < b.N; i++ {
PreStrBuilder(100000, "wxy")
}
}
func BenchmarkPreByteBuffer(b *testing.B) {
for i := 0; i < b.N; i++ {
PreStrByteBuffer(100000, "wxy")
}
}
è¿Âè¡Âç»ÂæÂÂï¼Â
$ go test -bench .
goos: windows
goarch: amd64
pkg: GoProject1
cpu: 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz
BenchmarkPlus-16 1 1126084200 ns/op
BenchmarkStrBuilder-16 3982 284773 ns/op
BenchmarkByteBuffer-16 2947 485091 ns/op
BenchmarkPreStrBuilder-16 4771 278961 ns/op
BenchmarkPreByteBuffer-16 3310 364676 ns/op
PASS
ok GoProject1 6.457s
- 使ç¨
ï¼Â
æ¼æÂ¥æ§è½æÂÂå·®ï¼Âstrings.Builder
ï¼Âbytes.Buffer
ç¸è¿Âï¼Âstrings.Builder
æ´快 - Ã¥ÂÂ符串å¨Goè¯Âè¨Âä¸Âæ¯ä¸Âå¯åÂÂç±»åÂÂï¼Âå ç¨å åÂÂ大å°Âæ¯åºå®ÂçÂÂ
- 使ç¨
ï¼Â
æ¯Â次é½ä¼ÂéÂÂæ°åÂÂé Âå å strings.Builder
ï¼Âbytes.Buffer
åºÂå±Âé½æ¯[]byteæ°ç»ÂãÂÂå åÂÂæ©容çÂÂçÂ¥ï¼Âä¸ÂéÂÂè¦Âæ¯Â次æ¼æÂ¥éÂÂæ°åÂÂé Âå åÂÂ- é¢ÂÃ¥ÂÂéÂ
ÂÃ¥ÂÂ
Ã¥ÂÂÃ¥ÂÂï¼Â
strings.Builder
ï¼Âbytes.Buffer
æ§è½é½æÂÂæÂÂæÂÂÃ¥ÂÂ
ç»ÂæÂÂä½Âä¼ÂÃ¥ÂÂ
示ä¾Â代ç Âï¼Â
func EmptyStructMap(n int) {
m := make(map[int]struct{})
for i := 0; i < n; i++ {
m[i] = struct{}{}
}
}
func BoolMap(n int) {
m := make(map[int]bool)
for i := 0; i < n; i++ {
m[i] = false
}
}
func BenchmarkEmptyStructMap(b *testing.B) {
for i := 0; i < b.N; i++ {
EmptyStructMap(100000000)
}
}
func BenchmarkBoolMap(b *testing.B) {
for i := 0; i < b.N; i++ {
BoolMap(100000000)
}
}
æ§è¡Âç»ÂæÂÂï¼Â
$ go test -bench .
goos: windows
goarch: amd64
pkg: GoProject1
cpu: 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz
BenchmarkEmptyStructMap-16 1 13943515100 ns/op
BenchmarkBoolMap-16 1 14002905100 ns/op
PASS
ok GoProject1 28.215s
å¯以åÂÂç°使ç¨空ç»ÂæÂÂä½Âæ§è½è¾Â好ãÂÂ
使ç¨空ç»ÂæÂÂä½ÂèÂÂçÂÂå åÂÂï¼Â
- 空ç»ÂæÂÂä½Âstruct{}å®Âä¾Âä¸Âå æ®任ä½ÂçÂÂå åÂÂ空é´
- å¯ä½Â为åÂÂç§Âåºæ¯ä¸ÂçÂÂå ä½Â符使ç¨
- èÂÂçÂÂèµÂæºÂ
- 空ç»ÂæÂÂä½Âæ¬身堷å¤Âå¾Â强çÂÂè¯Âä¹Âï¼Âå³è¿ÂéÂÂä¸ÂéÂÂè¦Âä»»ä½Âå¼ï¼Âä» ä½Â为å ä½Â符
atomicÃ¥ÂÂ
示ä¾Â代ç Âï¼Â
type atomicCounter struct {
i int32
}
func AtomicAddOne(c *atomicCounter) {
atomic.AddInt32(&c.i, 1)
}
type mutexCounter struct {
i int32
m sync.Mutex
}
func MutexAddOne(c *mutexCounter) {
c.m.Lock()
c.i++
c.m.Unlock()
}
func BenchmarkAtomicAddOne(b *testing.B) {
var c atomicCounter
b.ResetTimer()
for i := 0; i < b.N; i++ {
AtomicAddOne(&c)
}
}
func BenchmarkMutexAddOne(b *testing.B) {
var c mutexCounter
b.ResetTimer()
for i := 0; i < b.N; i++ {
MutexAddOne(&c)
}
}
è¿Âè¡Âç»ÂæÂÂï¼Â
$ go test -bench .
goos: windows
goarch: amd64
pkg: GoProject1
cpu: 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz
BenchmarkAtomicAddOne-16 255736488 4.565 ns/op
BenchmarkMutexAddOne-16 99685160 13.66 ns/op
PASS
ok GoProject1 3.101s
使ç¨atomicå ï¼Â
- éÂÂçÂÂå®Âç°æ¯éÂÂè¿ÂæÂÂä½Âç³»ç»ÂæÂ¥å®Âç°ï¼Âå±ÂäºÂç³»ç»Âè°Âç¨
- atomicæÂÂä½Âæ¯éÂÂè¿Â硬件å®Âç°ï¼ÂæÂÂçÂÂæ¯ÂéÂÂé«Â
- sync.MutexåºÂ该ç¨æÂ¥ä¿Âæ¤ä¸Â段é»è¾Âï¼Âä¸Âä» ä» ç¨äºÂä¿Âæ¤ä¸Â个åÂÂéÂÂ
- 对äºÂéÂÂæ°å¼æÂÂä½Âï¼Âå¯以使ç¨atomic.Valueï¼Âè½æ¿载ä¸Â个interface{}
å°Âç»Â
- é¿å Â常è§ÂçÂÂæ§è½é·é±å¯以ä¿Âè¯Â大é¨åÂÂç¨ÂåºÂçÂÂæ§è½
- æ®éÂÂåºÂç¨代ç Âï¼Âä¸Âè¦Âä¸Âå³å°追æ±Âç¨ÂåºÂçÂÂæ§è½
- è¶Âé«Â级çÂÂæ§è½ä¼ÂÃ¥ÂÂæÂÂ段è¶Â容æÂÂåºç°é®é¢Â
- å¨满足æ£确å¯é ãÂÂç®Âæ´Â渠æ°çÂÂè´¨éÂÂè¦Âæ±ÂçÂÂÃ¥ÂÂæÂÂä¸ÂæÂÂé«Âç¨ÂåºÂæ§è½
pprofæ§è½è°Âä¼Â
å¨计ç®Âæºæ§è½è°Âè¯Âé¢ÂÃ¥ÂÂéÂÂï¼Âprofiling æ¯æÂÂ对åºÂç¨ç¨ÂåºÂçÂÂçÂȌÂÂï¼ÂçÂȌÂÂå°±æ¯åºÂç¨ç¨ÂåºÂ使ç¨ CPU Ã¥ÂÂå åÂÂçÂÂæ åµã Goè¯Âè¨Âæ¯ä¸Â个对æ§è½ç¹å«çÂÂéÂÂçÂÂè¯Âè¨Âï¼Âå æ¤è¯Âè¨Âä¸Âèª带亠profiling çÂÂåºÂãÂÂ
Goè¯Âè¨Â项ç®ä¸ÂçÂÂæ§è½ä¼ÂÃ¥ÂÂ主è¦ÂæÂÂ以ä¸Âå 个æ¹é¢ï¼Â
- CPU profileï¼ÂæÂ¥åÂÂç¨ÂåºÂç CPU 使ç¨æ åÂ括ÂæÂÂç §ä¸Âå®Âé¢ÂçÂÂÃ¥ÂȎÂÂéÂÂåºÂç¨ç¨ÂåºÂå¨ CPU Ã¥ÂÂå¯ÂÃ¥ÂÂå¨ä¸Âé¢çÂÂæ°æ®
- Memory Profileï¼ÂHeap Profileï¼Âï¼ÂæÂ¥åÂÂç¨ÂåºÂçÂÂå åÂÂ使ç¨æ åµ
- Block Profilingï¼ÂæÂ¥å goroutines ä¸Âå¨è¿Âè¡Âç¶æÂÂçÂÂæ åÂ括Âå¯以ç¨æÂ¥åÂÂæÂÂÃ¥ÂÂæÂ¥æ¾æÂȎÂÂçÂÂæ§è½ç¶é¢Â
- Goroutine Profilingï¼ÂæÂ¥å goroutines çÂÂ使ç¨æ åÂ括ÂæÂÂåª亠goroutineï¼Âå®Â们çÂÂè°Âç¨堳系æ¯æÂÂæ ·çÂÂ
éÂÂéÂÂæ§è½æ°æ®
Goè¯Âè¨Âå 置äºÂè·åÂÂç¨ÂåºÂçÂÂè¿Âè¡Âæ°æ®çÂÂ工堷ï¼Âå æ¬以ä¸Â两个æ ÂÃ¥ÂÂåºÂï¼Â
runtime/pprof
ï¼ÂéÂÂéÂÂ工堷åÂÂåºÂç¨è¿Âè¡Âæ°æ®è¿Âè¡ÂÃ¥ÂÂæÂÂnet/http/pprof
ï¼ÂéÂÂéÂÂæÂÂå¡åÂÂåºÂç¨è¿Âè¡Âæ¶æ°æ®è¿Âè¡ÂÃ¥ÂÂæÂÂ
pprofå¼Âå¯åÂÂï¼Âæ¯ÂéÂÂä¸Â段æ¶é´ï¼Â10msï¼Âå°±ä¼Âæ¶éÂÂä¸Âå½ÂÃ¥ÂÂçÂÂå Âæ Âä¿¡æ¯ï¼Âè·åÂÂÃ¥ÂÂ个å½æ°å ç¨çÂÂCPU以åÂÂå åÂÂèµÂæºÂï¼ÂæÂÂÃ¥ÂÂéÂÂè¿Â对è¿ÂäºÂéÂÂæ ·æ°æ®è¿Âè¡ÂÃ¥ÂÂæÂÂï¼Âå½¢æÂÂä¸Â个æ§è½åÂÂæÂÂæÂ¥åÂÂãÂÂ
注æÂÂï¼ÂæÂÂ们åªåºÂ该å¨æ§è½æµÂè¯ÂçÂÂæ¶åÂÂæÂÂå¨代ç Âä¸Âå¼Âå ¥pprofãÂÂ
æ¬ç¯ÂæÂÂç« åª对æÂÂå¡åÂÂåºÂç¨è¿Âè¡Âæ§è½åÂÂæÂÂãÂÂ
æÂÂå¡åÂÂåºÂç¨
å¦ÂæÂÂä½ çÂÂåºÂç¨ç¨ÂåºÂæ¯ä¸Âç´è¿Âè¡ÂçÂÂï¼Âæ¯Â妠web åºÂç¨ï¼Âé£ä¹Âå¯以使ç¨net/http/pprof
åºÂï¼Âå®Âè½å¤Âå¨æÂÂä¾ HTTP æÂÂå¡è¿Âè¡ÂÃ¥ÂÂæÂÂãÂÂ
å¦ÂæÂÂ使ç¨äºÂé»Â认çÂÂhttp.DefaultServeMux
ï¼ÂéÂÂ常æ¯代ç Âç´æ¥使ç¨ http.ListenAndServe(âÂÂ0.0.0.0:8000âÂÂ, nil)ï¼Âï¼ÂåªéÂÂè¦Âå¨你çÂÂweb server端代ç Âä¸ÂæÂÂå¦Âä¸Âæ¹å¼Â导åÂ
Â¥net/http/pprof
import _ "net/http/pprof"
å¦ÂæÂÂ你使ç¨èªå®Âä¹Âç Muxï¼ÂÃ¥ÂÂéÂÂè¦ÂæÂÂå¨注åÂÂä¸ÂäºÂè·¯ç±è§ÂÃ¥ÂÂï¼Â
r.HandleFunc("/debug/pprof/", pprof.Index)
r.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
r.HandleFunc("/debug/pprof/profile", pprof.Profile)
r.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
r.HandleFunc("/debug/pprof/trace", pprof.Trace)
å¦ÂæÂÂ你使ç¨çÂÂæ¯ginæ¡Âæ¶ï¼Âé£ä¹Âæ¨èÂÂ使ç¨github.com/gin-contribâ¦ï¼Âå¨代ç Âä¸ÂéÂÂè¿Â以ä¸Âå½令注åÂÂpprofç¸堳路ç±ãÂÂ
pprof.Register(router)
ä¸Â管åªç§Âæ¹å¼Âï¼Âä½ ç HTTP æÂÂå¡é½ä¼Âå¤Âåºhttp://host:port/debug/pprof
ï¼Â访é®å®Âä¼Âå¾Âå°类似ä¸Âé¢çÂÂÃ¥ÂÂ
容ï¼Â
è¿Â个路å¾Âä¸Âè¿ÂæÂÂå 个åÂÂ页é¢ï¼Â
- /debug/pprof/profileï¼Â访é®è¿Â个é¾æÂ¥ä¼Âèªå¨è¿Âè¡ CPU profilingï¼ÂæÂÂç» 30sï¼Â并çÂÂæÂÂä¸Â个æÂÂ件ä¾Âä¸Âè½½
- /debug/pprof/heapï¼ Memory Profiling çÂÂè·¯å¾Âï¼Â访é®è¿Â个é¾æÂ¥ä¼Âå¾Âå°ä¸Â个å å Profiling ç»ÂæÂÂçÂÂæÂÂ件
- /debug/pprof/blockï¼Âblock Profiling çÂÂè·¯å¾Â
- /debug/pprof/goroutinesï¼Âè¿Âè¡Âç goroutines Ã¥ÂÂ表ï¼Â以åÂÂè°Âç¨堳系
ä¸Âé¢æ¯详ç»ÂçÂÂ解éÂÂï¼Â
Allocs: è¿ÂÃ¥ÂȾÂÂæÂÂå åÂÂÃ¥ÂÂé ÂçÂÂæ½样
Block: 导è´åÂÂæÂ¥åÂÂè¯Âé»å¡ÂçÂÂå Âæ Âè·Â踪
Cmdline: å½ÂÃ¥ÂÂç¨ÂåºÂçÂÂå½令è¡Âè°Âç¨
Goroutine: æÂÂæÂÂå½Âå goroutine çÂÂå Âæ Âè·Â踪ãÂÂ使ç¨ debug = 2ä½Â为æ¥询åÂÂæ°ï¼Â以ä¸Âæªæ¢å¤ÂçÂÂæÂÂæ Âç¸åÂÂçÂÂæ ¼å¼Â导åºãÂÂ
Heap: æ´»å¨对象çÂÂå åÂÂÃ¥ÂÂé ÂçÂÂæ½样ãÂÂå¨è·åÂÂå Â示ä¾Âä¹ÂÃ¥ÂÂï¼Âå¯以æÂÂå® gc GET Ã¥ÂÂæ°æÂ¥è¿Âè¡ GCãÂÂ
Mutex: 对äºÂç¨çÂÂäºÂæ¥对象çÂÂæÂÂæÂÂè è¿Âè¡Âè·Â踪å Âæ Â
profile: CPU é Âç½®æÂÂ件ãÂÂå¯以å¨秠GET Ã¥ÂÂæ°ä¸ÂæÂÂå®ÂæÂÂç»Âæ¶é´ãÂÂè·å¾Âæ¦Âè¦ÂæÂÂ件ä¹ÂÃ¥ÂÂï¼Â使ç¨ go 工堷 pprof å½令è°ÂæÂ¥æ¦Âè¦ÂæÂÂ件ãÂÂ
Threadcreate: 导è´åÂÂ建æ°æÂÂä½Âç³»ç»Â线ç¨ÂçÂÂå Âæ Âè·Â踪
Trace: å½ÂÃ¥ÂÂç¨ÂåºÂæ§è¡ÂçÂÂè·Â踪ãÂÂå¯以å¨秠GET Ã¥ÂÂæ°ä¸ÂæÂÂå®ÂæÂÂç»Âæ¶é´ãÂÂè·å¾Âè·Â踪æÂÂ件åÂÂï¼Â使ç¨ go tool trace å½令è°ÂæÂ¥è·Â踪ãÂÂ
go tool pprofå½令
ä¸Â管æ¯工åÂ
·åÂÂåºÂç¨è¿Âæ¯æÂÂå¡åÂÂåºÂç¨ï¼ÂæÂÂ们使ç¨ç¸åºÂçÂÂpprofåºÂè·åÂÂæ°æ®ä¹ÂÃ¥ÂÂï¼Âä¸Âä¸ÂæÂ¥çÂÂé½è¦Â对è¿ÂäºÂæ°æ®è¿Âè¡ÂÃ¥ÂÂæÂÂï¼ÂæÂÂ们å¯以使ç¨go tool pprof
å½令è¡Âå·¥åÂ
·ãÂÂ
go tool pprof
æÂÂç®ÂÃ¥ÂÂçÂÂ使ç¨æ¹å¼Â为:
go tool pprof [binary] [source]
å ¶ä¸Âï¼Â
- binary æ¯åºÂç¨çÂÂäºÂè¿Âå¶æÂÂ件ï¼Âç¨æ¥解æÂÂÃ¥ÂÂç§Â符å·ï¼Â
- source 表示 profile æ°æ®çÂÂæÂ¥æºÂï¼Âå¯以æ¯æΡçÂÂæÂÂ件ï¼Âä¹Âå¯以æ¯ http å°åÂÂãÂÂ
注æÂÂäºÂ项@è·åÂÂç Profiling æ°æ®æ¯å¨æÂÂçÂÂï¼Âè¦Âæ³è·å¾ÂæÂÂæÂÂçÂÂæ°æ®ï¼Â请ä¿Âè¯ÂåºÂç¨å¤ÂäºÂè¾Â大çÂÂè´Âè½½ï¼Âæ¯Âå¦Âæ£å¨çÂÂæÂÂä¸Âè¿Âè¡ÂçÂÂæÂÂå¡ï¼ÂæÂÂè éÂÂè¿Âå ¶ä»Â工堷模æÂÂ访é®åÂÂÃ¥ÂÂï¼ÂãÂÂå¦åÂÂå¦ÂæÂÂåºÂç¨å¤ÂäºÂ空é²ç¶æÂÂï¼Âå¾Âå°çÂÂç»ÂæÂÂå¯è½没æÂÂä»»ä½ÂæÂÂä¹ÂãÂÂ
项ç®è°Âä¼ÂÃ¥ÂÂæÂÂ
æ¬æ¡Âä¾Â使ç¨äºÂblob项ç®âÂÂâÂÂ类似åÂÂ客çÂÂ管çÂÂç³»ç»Âï¼Âç¨beegoå®Âç°ï¼ÂæºÂç ÂæÂÂå·²ç»Âæ¾å°äºÂgithubä»ÂåºÂéÂÂï¼Âgithub.com/uestc-wxy/bâ¦ï¼ÂéÂÂé¢ä¹ÂæÂÂ详ç»ÂçÂÂ使ç¨说æÂÂãÂÂ
ä¿®æ¹main.go
为äºÂè½对è¿Â个项ç®è¿Âè¡Âè°Âä¼ÂÃ¥ÂÂæÂÂï¼ÂéÂÂè¦Âå¨main.go
æÂÂ件éÂÂæ·»å å è¡Â代ç Âï¼Â
import (
"net/http"
_ "net/http/pprof"
)
go func() {
http.ListenAndServe("localhost:8080", nil)
}()
ä¸Âé¢æ¯修æ¹åÂÂçÂÂmain.go
ï¼ÂåªéÂÂè¦Âä¿®æ¹è¿Âä¸Â个æÂÂ件ï¼Âï¼Â
package main
import (
_ "blob/models"
_ "blob/routers"
"blob/utils"
"fmt"
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/server/web"
_ "github.com/go-sql-driver/mysql"
"net/http"
_ "net/http/pprof"
)
func init() {
username, _ := web.AppConfig.String("username")
password, _ := web.AppConfig.String("password")
host, _ := web.AppConfig.String("host")
port, _ := web.AppConfig.String("port")
database, _ := web.AppConfig.String("database")
datasource := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&loc=Local", username, password, host, port, database)
err := orm.RegisterDataBase("default", "mysql", datasource)
if err != nil {
fmt.Printf("%v\n", err)
}
err = orm.RunSyncdb("default", false, true)
if err != nil {
fmt.Printf("%v\n", err)
}
}
func main() {
web.InsertFilter("/cms/index/*", web.BeforeRouter, utils.CmsLoginFilter)
orm.RunCommand()
go func() {
http.ListenAndServe("localhost:8080", nil)
}()
web.Run()
}
å®Â裠go-wrk
为äºÂ使æ°æ®ç´è§Â便äºÂÃ¥ÂÂæÂÂï¼ÂéÂÂè¦Â使ç¨åÂÂæµÂ工堷ãÂÂ
æ¨èÂÂ使ç¨ï¼Âgithub.com/wg/wrk æ github.com/adjust/go-wâ¦ï¼Âç±äºÂæÂÂæ¯Windowsç³»ç»Âï¼ÂäºÂæ¯éÂÂæ©äºÂÃ¥ÂÂè ï¼Âå 为åÂÂè 对Windows并ä¸Âæ¯å¾ÂÃ¥ÂÂ好ï¼Âè½ç¶å®ÂçÂÂstaræ°è¿Âè¦Âå¤ÂäºÂãÂÂ
å¨GOPATH/src
è·¯å¾Âç»Â端ä¾Â次è¿Âè¡Âä¸ÂÃ¥ÂÂå½令ï¼Â注æÂÂæ¯GOPATH/src
ï¼Â
git clone https://github.com/adjust/go-wrk.git
cd go-wrk
go mod init
go mod tidy
go build
è¿Âæ¶你ä¼ÂÃ¥ÂÂç°go-wrk
项ç®éÂÂä¼Âå¤Âåºgo-wrk.exe
æÂÂ件ï¼Â为äºÂæ¹便使ç¨æÂÂéÂÂæ©æÂÂå®Âæ¾å¨ï¼Âä¹Âå°±æ¯å¤Âå¶ç²Âè´´è¿Âå»ï¼ÂGOPATH/bin
ç®å½Âä¸Âï¼Âå½Âç¶你å¾ÂæÂÂGOPATH/bin
æ¾å¨ç¯å¢ÂÃ¥ÂÂéÂÂéÂÂé¢ï¼Âè³äºÂ为ä»Âä¹Âå°Âgo-wrk.exe
æ¾å¨$GOPATH/bin
éÂÂé¢ï¼Âè¿Âä¼¼ä¹Âæ¯ä¸Âç§Âè§ÂèÂÂãÂÂæÂÂçÂÂÃ¥Â
¶ä»ÂæÂÂç« ä¹ÂæÂÂæÂÂå°è¿ÂãÂÂ
éÂÂè¿Âä¸Âè¿°æÂÂä½Âå°±å¯以å¨任ä½Âå°æ¹使ç¨go-wrk
å½令äºÂãÂÂ
å½令è¡Â交äºÂçÂÂé¢
é¦Âå ÂéÂÂè¦Âä¿Âè¯ÂæÂÂ们çÂÂ项ç®éÂÂè¦Âå¨æΡè·Âèµ·æÂ¥ãÂÂå¨项ç®根ç®å½Âç»Â端è¿Âè¡Âï¼Â
go build
./blob
å½Âç¶ä¹Âå¯以使ç¨bee run
å½令ï¼Âæ¯Âç«Âè¿Âæ¯beego项ç®ç¹æÂÂçÂÂè¿Âè¡Âæ¹å¼ÂãÂÂ
ç¶åÂÂå¨该路å¾Âä¸ÂÃ¥ÂÂå¼Âä¸Â个ç»Â端ï¼Âç¨æÂ¥è·ÂÃ¥ÂÂæµÂï¼Âæ§è¡Âå½令ï¼Â
go-wrk -n 50000 http://localhost:8080/
æ§è¡Âä¸Âé¢çÂÂ代ç Âä¼Âè¿Â堥交äºÂçÂÂé¢å¦Âä¸Âï¼Â
(base) PS F:\GolandProjects\beegoProject\blob> go-wrk -n 50000 http://localhost:8080/
==========================BENCHMARK==========================
URL: http://localhost:8080/
Used Connections: 100
Used Threads: 1
Total number of calls: 50000
===========================TIMINGS===========================
Total time passed: 22.95s
Avg time per request: 45.76ms
Requests per second: 2179.05
Median time per request: 45.14ms
99th percentile time: 53.77ms
Slowest time for request: 119.00ms
=============================DATA=============================
Total response body sizes: 251100000
Avg response body per request: 5022.00 Byte
Transfer rate per second: 10943208.24 Byte/s (10.94 MByte/s)
==========================RESPONSES==========================
20X Responses: 50000 (100.00%)
30X Responses: 0 (0.00%)
40X Responses: 0 (0.00%)
50X Responses: 0 (0.00%)
Errors: 0 (0.00%)
æÂ¥çÂÂÃ¥ÂÂå¼Âä¸Â个ç»Â端ï¼Â以使ç¨pprof
æÂ¥åÂÂæÂÂãÂÂ
æ§è¡Âå½令ï¼Â
go tool pprof http://127.0.0.1:8080/debug/pprof/profile
æ§è¡Âä¸Âé¢çÂÂ代ç Âä¼Âè¿Â堥交äºÂçÂÂé¢å¦Âä¸Âï¼Â
(base) PS F:\GolandProjects\beegoProject\blob> go tool pprof http://127.0.0.1:8080/debug/pprof/profile
Fetching profile over HTTP from http://127.0.0.1:8080/debug/pprof/profile
Saved profile in C:\Users\19393\pprof\pprof.blob.exe.samples.cpu.004.pb.gz
File: blob.exe
Build ID: F:\GolandProjects\beegoProject\blob\blob.exe2023-08-01 16:06:16.7719208 +0800 CST
Type: cpu
Time: Aug 1, 2023 at 4:10pm (CST)
Duration: 30s, Total samples = 44.41s (148.02%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof)
æÂÂ们å¯以å¨交äºÂçÂÂé¢è¾ÂÃ¥Â
Â¥top5
æÂ¥æÂ¥çÂÂç¨ÂåºÂä¸Âå ç¨CPUÃ¥ÂÂ5ä½ÂçÂÂå½æ°ï¼Â
(pprof) top5
Showing nodes accounting for 27510ms, 61.95% of 44410ms total
Dropped 859 nodes (cum <= 222.05ms)
Showing top 5 nodes out of 246
flat flat% sum% cum cum%
21960ms 49.45% 49.45% 22080ms 49.72% runtime.cgocall
2010ms 4.53% 53.97% 5980ms 13.47% runtime.scanobject
1410ms 3.17% 57.15% 1740ms 3.92% runtime.greyobject
1340ms 3.02% 60.17% 1730ms 3.90% runtime.findObject
790ms 1.78% 61.95% 790ms 1.78% runtime.stdcall2
å ¶ä¸Âï¼Â
- flatï¼Âå½ÂÃ¥ÂÂå½æ°å ç¨CPUçÂÂèÂÂæ¶
- flatï¼Â:å½ÂÃ¥ÂÂå½æ°å ç¨CPUçÂÂèÂÂæ¶ç¾åÂÂæ¯Â
- sun%ï¼Âå½æ°å ç¨CPUçÂÂèÂÂæ¶累计ç¾åÂÂæ¯Â
- cumï¼Âå½ÂÃ¥ÂÂå½æ°å ä¸Âè°Âç¨å½ÂÃ¥ÂÂå½æ°çÂÂå½æ°å ç¨CPUçÂÂæÂȏÂÂæ¶
- cum%ï¼Âå½ÂÃ¥ÂÂå½æ°å ä¸Âè°Âç¨å½ÂÃ¥ÂÂå½æ°çÂÂå½æ°å ç¨CPUçÂÂæÂȏÂÂæ¶ç¾åÂÂæ¯Â
- æÂÂÃ¥ÂÂä¸ÂÃ¥ÂÂï¼Âå½æ°åÂÂ称
æÂÂ们åÂÂç°ä¸Âé¢并没æÂÂæÂÂ们èª己åÂÂçÂÂå½æ°ï¼ÂæÂÂ以æ¬项ç®çÂÂæ§è½è¿Âæ¯ä¸ÂéÂÂçÂÂãÂÂå¨大å¤Âæ°çÂÂæ åµä¸Âï¼ÂæÂÂ们å¯以éÂÂè¿ÂÃ¥ÂÂæÂÂè¿ÂäºÂÃ¥ÂÂå¾Âåºä¸Â个åºÂç¨ç¨ÂåºÂçÂÂè¿Âè¡Âæ åÂ括Â并对ç¨ÂåºÂè¿Âè¡Âä¼ÂÃ¥ÂÂãÂÂ
æÂÂ们è¿Âå¯以使ç¨list å½æ°åÂÂ
å½令æÂ¥çÂÂÃ¥Â
·ä½ÂçÂÂå½æ°åÂÂæÂÂï¼Âä¾Âå¦Âæ§è¡Âlist cgocall
æÂ¥çÂÂæÂÂ们ç¼ÂÃ¥ÂÂçÂÂå½æ°çÂÂ详ç»ÂÃ¥ÂÂæÂÂãÂÂ
(pprof) list cgocall
Total: 44.41s
ROUTINE ======================== runtime.cgocall in F:\Users\19393\sdk\go1.20.4\src\runtime\cgocall.go
21.96s 22.08s (flat, cum) 49.72% of Total
. . 123:func cgocall(fn, arg unsafe.Pointer) int32 {
. . 124: if !iscgo && GOOS != "solaris" && GOOS != "illumos" && GOOS != "windows" {
. . 125: throw("cgocall unavailable")
. . 126: }
. . 127:
. . 128: if fn == nil {
. . 129: throw("cgocall nil")
. . 130: }
. . 131:
. . 132: if raceenabled {
. . 133: racereleasemerge(unsafe.Pointer(&racecgosync))
. . 134: }
. . 135:
. . 136: mp := getg().m
. . 137: mp.ncgocall++
. . 138: mp.ncgo++
. . 139:
. . 140: // Reset traceback.
. . 141: mp.cgoCallers[0] = 0
. . 142:
. . 143: // Announce we are entering a system call
. . 144: // so that the scheduler knows to create another
. . 145: // M to run goroutines while we are in the
. . 146: // foreign code.
. . 147: //
. . 148: // The call to asmcgocall is guaranteed not to
. . 149: // grow the stack and does not allocate memory,
. . 150: // so it is safe to call while "in a system call", outside
. . 151: // the $GOMAXPROCS accounting.
. . 152: //
. . 153: // fn may call back into Go code, in which case we'll exit the
. . 154: // "system call", run the Go code (which may grow the stack),
. . 155: // and then re-enter the "system call" reusing the PC and SP
. . 156: // saved by entersyscall here.
21.94s 21.94s 157: entersyscall()
. . 158:
. . 159: // Tell asynchronous preemption that we're entering external
. . 168:
. . 169: // Update accounting before exitsyscall because exitsyscall may
. . 170: // reschedule us on to a different M.
. . 171: mp.incgo = false
. . 172: mp.ncgo--
. . 173:
20ms 40ms 174: osPreemptExtExit(mp)
. . 175:
. 100ms 176: exitsyscall()
. . 177:
. . 178: // Note that raceacquire must be called only after exitsyscall has
. . 179: // wired this M to a P.
. . 180: if raceenabled {
. . 181: raceacquire(unsafe.Pointer(&racecgosync))
éÂÂè¿ÂÃ¥ÂÂæÂÂÃ¥ÂÂç°大é¨åÂÂCPUèµÂæºÂ被157è¡Âå ç¨ï¼ÂèÂÂæ¶21.94sãÂÂ
å¾形åÂÂ
æÂÂè å¯以ç´æÂ¥è¾Âå ¥webï¼ÂéÂÂè¿Âsvgå¾çÂÂæ¹å¼ÂæÂ¥çÂÂç¨ÂåºÂä¸Â详ç»ÂçÂÂCPUå ç¨æ åµã æ³è¦ÂæÂ¥çÂÂå¾形åÂÂçÂÂçÂÂé¢é¦Âå ÂéÂÂè¦Âå®Â裠graphvizå¾形åÂÂ工堷ãÂÂç±äºÂæÂÂæ¯Windowsç³»ç»Âï¼Âè¿Âå ¥å®Âç½Âä¸Âè½½graphvizï¼Âgraphviz.gitlab.io/download/
ä¸Âè½½å®ÂÃ¥ÂÂæÂÂå¼Âexe
æÂÂ件è¿Âè¡Âå®Âè£Â
ãÂÂ
è¿ÂéÂÂå¾éÂÂ第äºÂ个ï¼Âèªå¨帮你é Âç½®ç¯å¢ÂÃ¥ÂÂéÂÂãÂÂÃ¥ÂÂé¢快æ·æ¹å¼ÂæÂÂéÂÂæ©ä¸ÂÃ¥ÂÂ建ãÂÂ
å®Âè£Â
å®Âæ¯ÂÃ¥ÂÂæÂÂå¼Âç»Â端è¿Âè¡Âdot -v
æ£ÂæÂ¥æ¯å¦å®Âè£Â
æÂÂÃ¥ÂÂï¼Âå®Âè£Â
æÂÂÃ¥ÂÂåºÂ该ä¼Âæ¾示以ä¸ÂÃ¥ÂÂ
容ï¼Â
(base) PS C:\Users\19393> dot -v
dot - graphviz version 8.1.0 (20230707.0739)
libdir = "F:\Program Files\Graphviz\bin"
Activated plugin library: gvplugin_dot_layout.dll
Using layout: dot:dot_layout
Activated plugin library: gvplugin_core.dll
Using render: dot:core
Using device: dot:dot:core
The plugin configuration file:
F:\Program Files\Graphviz\bin\config6
was successfully loaded.
render : cairo dot dot_json fig gdiplus json json0 map mp pic pov ps svg tk xdot xdot_json
layout : circo dot fdp neato nop nop1 nop2 osage patchwork sfdp twopi
textlayout : textlayout
device : bmp canon cmap cmapx cmapx_np dot dot_json emf emfplus eps fig gif gv imap imap_np ismap jpe jpeg jpg json json0 metafile mp pdf pic plain plain-ext png pov ps ps2 svg tif tiff tk xdot xdot1.2 xdot1.4 xdot_json
loadimage : (lib) bmp eps gif jpe jpeg jpg png ps svg
è¾ÂÃ¥Â
Â¥webÃ¥ÂÂ确认graphviz
å®Âè£Â
ç®å½Âä¸ÂçÂÂbinæÂÂ件夹æÂÂæ 被添å å°Pathç¯å¢ÂÃ¥ÂÂéÂÂï¼ÂæÂÂæ·»å çÂÂç³»ç»ÂÃ¥ÂÂéÂÂï¼Âä¸ÂãÂÂ
æÂ¥ä¸ÂæÂ¥æÂÂ们å°Âè¯Âç¨å¾形åÂÂçÂÂçÂÂé¢æÂ¥è¿Âè¡ÂÃ¥ÂÂæÂÂãÂÂ
Ã¥Â
Âä¿Âè¯Âèª己çÂÂbeego
项ç®è¿Âè¡Âå¨æΡä¸Âï¼ÂÃ¥ÂÂå¼Âä¸Â个ç»Â端è·ÂÃ¥ÂÂæµÂï¼Âgo-wrk -n 50000 http://localhost:8080/
ï¼Âå¦å¤ÂÃ¥ÂÂæÂ¥ä¸Â个åÂÂç»Â端è·Âpprof
ï¼Âæ§è¡Âå½令ï¼Âgo tool pprof http://127.0.0.1:8080/debug/pprof/profile
ãÂÂ
è·Âpprof
çÂÂç»Â端å¦Âä¸Âï¼Â
(base) PS F:\GolandProjects\beegoProject\blob> go tool pprof http://127.0.0.1:8080/debug/pprof/profile
Fetching profile over HTTP from http://127.0.0.1:8080/debug/pprof/profile
Saved profile in C:\Users\19393\pprof\pprof.blob.exe.samples.cpu.008.pb.gz
File: blob.exe
Build ID: F:\GolandProjects\beegoProject\blob\blob.exe2023-08-01 16:06:16.7719208 +0800 CST
Type: cpu
Time: Aug 1, 2023 at 7:02pm (CST)
Duration: 30s, Total samples = 44.25s (147.48%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) web
(pprof)
ç±äºÂè¾ÂÃ¥Â
¥äºÂwebå½令ï¼ÂæµÂè§Âå¨ä¼Âèªå¨弹åºæÂ¥çÂÂsvg
çÂÂ页é¢ï¼Â
å ³äºÂå¾形çÂÂ说æÂÂï¼ æ¯Â个æ¡Â代表ä¸Â个å½æ°ï¼ÂçÂÂ论ä¸Âæ¡ÂçÂÂè¶Â大表示å ç¨çÂÂCPUèµÂæºÂè¶Âå¤Âã æ¹æ¡Âä¹Âé´çÂÂ线æ¡代表å½æ°ä¹Âé´çÂÂè°Âç¨堳系ã 线æ¡ä¸ÂçÂÂæ°åÂÂ表示å½æ°è°Âç¨çÂÂæ¶é´ã æ¹æ¡Âä¸ÂçÂÂ第ä¸Âè¡Âæ°åÂÂ表示å½ÂÃ¥ÂÂå½æ°å ç¨CPUçÂÂç¾åÂÂæ¯Âï¼Â第äºÂè¡Âæ°åÂÂ表示å½ÂÃ¥ÂÂå½æ°累计å ç¨CPUçÂÂç¾åÂÂæ¯ÂãÂÂ
é¤äºÂÃ¥ÂÂæÂÂCPUæ§è½æ°æ®ï¼Âpprofä¹Âæ¯æÂÂÃ¥ÂÂæÂÂå åÂÂæ§è½æ°æ®ãÂÂæ¯Âå¦Âï¼Â使ç¨ä¸Âé¢çÂÂå½令åÂÂæÂÂhttpæÂÂå¡çÂÂheapæ§è½æ°æ®ï¼ÂæÂ¥çÂÂå½ÂÃ¥ÂÂç¨ÂåºÂçÂÂå åÂÂå ç¨以åÂÂçÂÂç¹å åÂÂ对象使ç¨çÂÂæ åµãÂÂ
# æÂ¥çÂÂÃ¥ÂÂ
Ã¥ÂÂå ç¨æ°æ®
go tool pprof -inuse_space http://127.0.0.1:8080/debug/pprof/heap
go tool pprof -inuse_objects http://127.0.0.1:8080/debug/pprof/heap
# æÂ¥çÂÂ临æ¶åÂÂ
Ã¥ÂÂÃ¥ÂÂéÂ
Âæ°æ®
go tool pprof -alloc_space http://127.0.0.1:8080/debug/pprof/heap
go tool pprof -alloc_objects http://127.0.0.1:8080/debug/pprof/heap
以ä¸Âæ¯æÂ¥çÂÂå åÂÂå ç¨æ°æ®çÂÂ示ä¾Âï¼Â
ç«ç°å¾
ç«ç°å¾ï¼ÂFlame Graphï¼Âæ¯ Bredan Gregg Ã¥ÂÂ建çÂÂä¸Âç§Âæ§è½åÂÂæÂÂå¾表ï¼Âå 为å®ÂçÂÂæ ·åÂÂè¿Âä¼¼ ðÂÂ¥èÂÂå¾ÂÃ¥ÂÂãÂÂ
å¯以éÂÂè¿Âå¦Âä¸Âæ¹å¼ÂæÂ¥æÂÂå¼Âç«ç°å¾ï¼Â
- Ã¥Â
ÂæÂÂÃ¥ÂÂæµÂè·Âä¸Âï¼Â
go-wrk -n 50000 http://localhost:8080/
- 项ç®根ç®å½Âæ°å¼Âä¸Â个ç»Â端ï¼Âè¿Âè¡Â
go tool pprof -http=:5200 http://127.0.0.1:8080/debug/pprof/profile
ï¼Â30sÃ¥ÂÂï¼ÂæµÂè§Âå¨ä¼Âèªå¨跳åºæ°çÂÂé¢ï¼Âhttp://localhost:5200/ui/ï¼Âå¦Âä¸Âï¼Â
- è·Âä¹ÂÃ¥ÂÂçÂÂå¾形åÂÂçÂÂé¢差ä¸Âå¤Âï¼ÂæÂ¥ä¸ÂæÂ¥ç¹å»ä¸Âå¾ä¸Âå¾示任ä¸Â个便è½çÂÂå°ç«ç°å¾ãÂÂ
èÂÂçÂÂç«ç°å¾ï¼Â
æ°çÂÂç«ç°å¾ï¼Â
ç«ç°å¾çÂÂä¼Âç¹æ¯å®Âæ¯å¨æÂÂçÂÂï¼Âå¯以éÂÂè¿Âç¹å»æ¯Â个æ¹åÂÂæÂÂ¥ Ã¥ÂÂæÂÂå®Âä¸Âé¢çÂÂå 容ãÂÂ
ç«ç°å¾çÂÂè°Âç¨顺åºÂä»Âä¸Âå°ä¸Âï¼Âæ¯Â个æ¹åÂÂ代表ä¸Â个å½æ°ï¼Âå®Âä¸Âé¢ä¸Âå±Â表示è¿Â个å½æ°ä¼Âè°Âç¨åªäºÂå½æ°ï¼Âæ¹åÂÂçÂÂ大å°Â代表äºÂå ç¨ CPU 使ç¨çÂÂé¿çÂÂãÂÂç«ç°å¾çÂÂé Âè²并没æÂÂç¹æ®ÂçÂÂæÂÂä¹Âï¼Âé»Â认çÂÂ红ãÂÂé»Âé Âè²æ¯为äºÂæ´åÂÂç«ç°èÂÂå·²ãÂÂ
ç«ç°å¾çÂÂy轴表示cpuè°Âç¨æ¹æ³ÂçÂÂå ÂÃ¥ÂÂï¼Âx轴表示å¨æ¯Â个éÂÂæ ·è°Âç¨æ¶é´å ï¼Âæ¹æ³ÂæÂÂå çÂÂæ¶é´ç¾åÂÂæ¯Âï¼Âè¶Â宽代表å æ®cpuæ¶é´è¶Âå¤ÂãÂÂéÂÂè¿Âç«ç°å¾æÂÂ们就å¯以æ´渠æ¥ÂçÂÂæ¾åºèÂÂæ¶é¿çÂÂå½æ°è°Âç¨ï¼Âç¶åÂÂä¸ÂæÂÂçÂÂä¿®æ£代ç Âï¼ÂéÂÂæ°éÂÂæ ·ï¼Âä¸ÂæÂÂä¼ÂÃ¥ÂÂãÂÂ
æ¤å¤Âè¿Âå¯以åÂÂå©ç«ç°å¾åÂÂæÂÂå åÂÂæ§è½æ°æ®ï¼Â
go tool pprof -http=:5200 -inuse_space http://127.0.0.1:8080/debug/pprof/heap
go tool pprof -http=:5200 -inuse_objects http://127.0.0.1:8080/debug/pprof/heap
go tool pprof -http=:5200 -alloc_space http://127.0.0.1:8080/debug/pprof/heap
go tool pprof -http=:5200 -alloc_objects http://127.0.0.1:8080/debug/pprof/heap
å åÂÂæ§è½ç«ç°å¾示ä¾Âï¼Â