go基础内容实操

48 阅读4分钟

1 并发原语

  • sync.Once
var (
	once      sync.Once
	initValue int
)

func main() {
	initFn := func() {
		fmt.Println("initialization function is called.")
		initValue = 100
	}
	for i := 0; i < 10; i++ {
		go func() {
			once.Do(initFn)
			fmt.Println("initValue:", initValue)
		}()
	}
	time.Sleep(10 * time.Second)
}
initialization function is called.
initValue: 100
initValue: 100
initValue: 100
......
  • sync.Cond
func main() {
	var cond sync.Cond
	cond.L = new(sync.Mutex) // 初始化条件变量时需要一个互斥锁

	// goroutine 1: 等待条件满足
	go func() {
		cond.L.Lock() // 进入临界区
		fmt.Println("Waiting for condition...")
		cond.Wait() // 等待通知,此时会释放互斥锁并阻塞
		fmt.Println("Condition has been broadcasted.")
		cond.L.Unlock() // 离开临界区
	}()

	// goroutine 2: 在1秒后发送通知
	go func() {
		time.Sleep(1 * time.Second)
		cond.L.Lock() // 进入临界区
		fmt.Println("Broadcasting the condition...")
		cond.Broadcast() // 发送通知给所有等待的 goroutine
		cond.L.Unlock()  // 离开临界区
	}()

	// 等待 goroutine 完成
	time.Sleep(10 * time.Second)
}
go run .\main.go
Waiting for condition...
Broadcasting the condition...
Condition has been broadcasted.
  • sync.Mutex
import "sync"

var sharedVar int
var mu sync.Mutex // 互斥锁

func readSharedVar() int {
    mu.Lock()
    defer mu.Unlock()
    return sharedVar
}

func writeSharedVar(value int) {
    mu.Lock()
    defer mu.Unlock()
    sharedVar = value
}
  • sync/atomic
func main() {
	var counter int32
	tmp := atomic.AddInt32(&counter, 10)
	fmt.Println(atomic.LoadInt32(&counter), tmp)
	atomic.CompareAndSwapInt32(&counter, 10, 12)
	fmt.Println(atomic.LoadInt32(&counter))
}

2 性能分析

pprof 是 Go 语言内置的性能分析工具,它可以帮助开发者了解程序的 CPU 和内存使用情况,以及 I/O 操作的性能瓶颈。

  • 导入net/http/pprof包
import (
	"net/http"
	_ "net/http/pprof"
)

pprof 的 HTTP 端点会被自动注册到默认的多路复用器上,当然也可以显式地进行注册,注意"_"的区别

import "net/http/pprof"

func main() {
    // 启动自定义的 HTTP 服务器
    http.ListenAndServe(":8080", nil)
    // 注册 pprof 端点到自定义的 HTTP 服务器
    http.HandleFunc("/debug/pprof/", pprof.Index)
    http.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
    http.HandleFunc("/debug/pprof/profile", pprof.Profile)
    http.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
    // ... 其他 pprof 端点
}
  • 启动http服务

如果应用本身是监听http的可以忽略,如果不是,需要启动一个http服务

  • 查看实时报告 image.png 如果要查看profile,可以使用使用go tool pprof profile命令打开
PS D:\test> go tool pprof http://localhost:8080/debug/pprof/profile
Fetching profile over HTTP from http://localhost:8080/debug/pprof/profile
Saved profile in C:\home\pprof\pprof.samples.cpu.007.pb.gz
Type: cpu
Time: May 30, 2024 at 4:35pm (CST)
Duration: 30.01s, Total samples = 10ms (0.033%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) 

输入top则可以看到,默认是一个30s区间的在线采样,采完后会下载至本地文件中

PS D:\test> go tool pprof http://localhost:8080/debug/pprof/profile
Fetching profile over HTTP from http://localhost:8080/debug/pprof/profile
Saved profile in C:\home\pprof\pprof.samples.cpu.007.pb.gz
Type: cpu
Time: Sep 23, 2024 at 4:06pm (CST)
Duration: 30.11s, Total samples = 200ms ( 0.66%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 190ms, 95.00% of 200ms total
Showing top 10 nodes out of 47
      flat  flat%   sum%        cum   cum%
      90ms 45.00% 45.00%       90ms 45.00%  runtime.cgocall
      20ms 10.00% 55.00%       20ms 10.00%  fmt.(*pp).printArg
      10ms  5.00% 60.00%       10ms  5.00%  net/http/pprof.sleep
      10ms  5.00% 65.00%       20ms 10.00%  runtime.execute
      10ms  5.00% 70.00%       10ms  5.00%  runtime.gogo
      10ms  5.00% 75.00%       10ms  5.00%  runtime.heapBitsForAddr
      10ms  5.00% 80.00%       10ms  5.00%  runtime.nextFreeFast
      10ms  5.00% 85.00%       40ms 20.00%  runtime.schedule
      10ms  5.00% 90.00%       10ms  5.00%  runtime.siftdownTimer
      10ms  5.00% 95.00%       10ms  5.00%  sync.(*Pool).Get
Type: inuse_space
Time: Sep 23, 2024 at 4:29pm (CST)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 12308.83kB, 100% of 12308.83kB total
Showing top 10 nodes out of 39
      flat  flat%   sum%        cum   cum%
 3082.01kB 25.04% 25.04%  3082.01kB 25.04%  bufio.NewWriterSize (inline)
 2568.06kB 20.86% 45.90%  2568.06kB 20.86%  bufio.NewReaderSize
 2049.25kB 16.65% 62.55%  2049.25kB 16.65%  net.newFD
 1024.41kB  8.32% 70.87%  1024.41kB  8.32%  runtime.malg
 1024.22kB  8.32% 79.19%  3074.42kB 24.98%  net/http.(*conn).readRequest
  512.50kB  4.16% 83.36%   512.50kB  4.16%  runtime.allocm
  512.17kB  4.16% 87.52%   512.17kB  4.16%  net/textproto.MIMEHeader.Set
  512.12kB  4.16% 91.68%  1024.20kB  8.32%  net/http.readRequest
  512.07kB  4.16% 95.84%   512.07kB  4.16%  net/url.parse
  512.02kB  4.16%   100%   512.02kB  4.16%  runtime.gcBgMarkWorker
  • flat (Flat Percentage): flat 列显示了在当前函数中直接消耗的 CPU 时间的比例。这个值是相对于总的采样时间的,并且只考虑了函数自身的执行时间,不包括任何被调用的子函数的时间。flat 有助于识别函数本身的执行效率。

  • sum (Self Percentage): sum% 列显示了函数自身的执行时间加上其所有子函数执行时间的总和占总采样时间的百分比。这个值包括了函数自身的 flat 时间以及所有递归调用和子调用的时间。sum% 有助于理解函数及其调用的子函数对整体性能的影响。

  • cum (Cumulative Percentage): cum% 列显示了从程序入口点到当前函数的整个调用链的累积 CPU 时间占总采样时间的百分比。这个值随着调用栈的深入而累积增加,显示了从程序开始执行到当前函数为止,所有函数执行时间的累积占比。cum% 有助于识别整个调用路径上的热点。

输入web则可以看到, 一个svg图片下载到了本地

image.png