golang [Go profiling snippets]用于分析目的的代码位#tags:golang,go,profiling,performance,measurement

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golang [Go profiling snippets]用于分析目的的代码位#tags:golang,go,profiling,performance,measurement相关的知识,希望对你有一定的参考价值。

package main

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"math/rand"
	"os"
	"os/signal"
	"syscall"
	"time"
)

const WhereTo = "/storage/p01/dummy/data.bin"
const RandomSeed = 987123
const BufSize = 1 << 20
const FileSizeLimit = 1 << 30

func AppendByte(slice []byte, data ...byte) []byte {
	m := len(slice)
	n := m + len(data)
	if n > cap(slice) { // if necessary, reallocate
		// allocate double what's needed, for future growth.
		newSlice := make([]byte, (n+1)*2)
		copy(newSlice, slice)
		slice = newSlice
	}
	slice = slice[0:n]
	copy(slice[m:n], data)
	return slice
}

type RandomInteger struct {
	rand.Source
}

// New creates a new random reader with a time source.
func New() io.Reader {
	return NewFrom(rand.NewSource(time.Now().UnixNano()))
}

// NewFrom creates a new reader from your own rand.Source
func NewFrom(src rand.Source) io.Reader {
	return &RandomInteger{src}
}

// Read satisfies io.Reader
func (r *RandomInteger) Read(p []byte) (n int, err error) {
	todo := len(p)
	offset := 0
	for {
		val := int64(r.Int63())
		for i := 0; i < 8; i++ {
			p[offset] = byte(val)
			todo--
			if todo == 0 {
				return len(p), nil
			}
			offset++
			val >>= 8
		}
	}
}

func main() {
	var b []byte
	var output string = WhereTo
	var bytecount int
	var writer *bufio.Writer
	var randbytes = make([]byte, 1024)

	if len(os.Args) > 1 {
		if os.Args[1] != "" {
			output = os.Args[1]
		}
	}

	// Cleanup on CTRL-C
	sig := make(chan os.Signal, 2)
	signal.Notify(sig, os.Interrupt, syscall.SIGTERM)

	go func() {
		<-sig
		fmt.Fprintf(os.Stdout,
			"Wrote %d bytes to %s\n", bytecount, WhereTo)
		os.Exit(0)
	}()

	source := rand.NewSource(RandomSeed)
	r := NewFrom(source)

	f, err := os.OpenFile(output, os.O_RDWR|os.O_CREATE, 0755)
	f.Truncate(0) // Start out with empty file in all cases

	writer = bufio.NewWriterSize(f, BufSize) // Writes out to file (f)

	if err != nil {
		fmt.Printf("%v\n", err)
	}

	for { // Loop over the bytes and keep appending until we reach limit
		if bytecount >= FileSizeLimit {
			break
		}
		b = make([]byte, 0)

		for i := 0; i < 1024; i++ {
			r.Read(randbytes)
			b = AppendByte(b, randbytes...)
		}

		if n, err := writer.Write(b); err != nil {
			log.Printf("%v\n", err)
		} else {
			bytecount += n
			writer.Flush() // flush after every 1MB
		}
		fmt.Printf("\r%dKB", bytecount>>10) // Update count of KB in place
	}
	fmt.Printf("\n")
}
package main

import (
	"fmt"
	"time"
)

// SleepyTime - how long to sleep?
const SleepyTime = 100

// GoRoutines - how many lightweight threads do we want?
const GoRoutines = 100

func main() {
	var ch chan struct{}
	for i := 0; i < GoRoutines; i++ {
		go func() {
			for {
				fmt.Printf("Sleeping for %d\n", SleepyTime)
				time.Sleep(time.Microsecond * SleepyTime)
			}
		}()
	}
	// Block forever, otherwise main exits before go-routines
	// have a chance to do anything substantial.
	<-ch
}

Golang Mutex profile

Go 1.8引入了mutex profile ,允许您捕获goroutine与mutex相关的堆栈跟踪。

你需要设置采样率runtime.SetMutexProfileFraction的值大于零,以便收集相关信息。

考虑下面的程序:

import _ "net/http/pprof"var mu sync.Mutexvar items = make(map[int]struct{})

runtime.SetMutexProfileFraction(5)for i := 0; i < 1000*1000; i++ {    go func(i int) {
        mu.Lock()        defer mu.Unlock()

        items[i] = struct{}{}
    }(i)
}

http.ListenAndServe(":8888", nil)

访问http://localhost:8888/debug/pprof/mutex 就会获取profile文件。 然后,您可以使用go tool pprof分析。

$ go tool pprof <binary> http://localhost:8888/debug/pprof/mutex?debug=1Fetching profile from http://localhost:8888/debug/pprof/mutex
Saved profile in /Users/jbd/pprof/pprof.mutexprofile.localhost:8888.contentions.delay.002.pb.gz
Entering interactive mode (type "help" for commands)
(pprof) list
Total: 27.15s
ROUTINE ======================== main.main.func1 in /Users/jbd/src/hello/mutexprofile/main.go     0     27.15s (flat, cum)   100% of Total
     .          .     18:		go func() {
     .          .     19:			mu.Lock()
     .          .     20:			defer mu.Unlock()
     .          .     21:
     .          .     22:			items[i] = struct{}{}
     .     27.15s     23:		}()
     .          .     24:	}
     .          .     25:	http.ListenAndServe(":8888", nil)
     .          .     26:}
ROUTINE ======================== runtime.goexit in /Users/jbd/go/src/runtime/asm_amd64.s     0     27.15s (flat, cum)   100% of Total
     .          .   2179:	RET
     .          .   2180:
     .          .   2181:// The top-most function running on a goroutine
     .          .   2182:// returns to goexit+PCQuantum.
     .          .   2183:TEXT runtime·goexit(SB),NOSPLIT,$0-0
     .     27.15s   2184:	BYTE	$0x90	// NOP
     .          .   2185:	CALL	runtime·goexit1(SB)	// does not return
     .          .   2186:	// traceback from goexit1 must hit code range of goexit
     .          .   2187:	BYTE	$0x90	// NOP
     .          .   2188:
     .          .   2189:TEXT runtime·prefetcht0(SB),NOSPLIT,$0-8ROUTINE ======================== sync.(*Mutex).Unlock in /Users/jbd/go/src/sync/mutex.go27.15s     27.15s (flat, cum)   100% of Total
     .          .    121:			return
     .          .    122:		}
     .          .    123:		// Grab the right to wake someone.
     .          .    124:		new = (old - 1<<mutexWaiterShift) | mutexWoken
     .          .    125:		if atomic.CompareAndSwapInt32(&m.state, old, new) {27.15s     27.15s    126:			runtime_Semrelease(&m.sema)
     .          .    127:			return
     .          .    128:		}
     .          .    129:		old = m.state
     .          .    130:	}
     .          .    131:}

如果测试中设置-mutexprofile,则该功能就被启用。

go test -mutexprofile=mutex.out

然后使用pprof工具可用于分析profile文件。

go tool pprof <binary> mutex.out

请参阅 runtime/pprof包获取更多详细信息


以上是关于golang [Go profiling snippets]用于分析目的的代码位#tags:golang,go,profiling,performance,measurement的主要内容,如果未能解决你的问题,请参考以下文章

Golang Mutex profile

解决go依赖包安装问题

[Go] 解决golang.org模块无法下载的问题

go编程语言 设置环境变量是怎么回事

go 性能剖析 PProf

linux 安装golang环境