- 與java比較
 
- GMP模型 官方
 - GMP模型 來源
 - G:Goroutine,实际上我们每次调用 go func 就是生成了一个 G。没有数量限制。但会受内存限制(Goroutine 创建需申请 2-4k 连续内存块)
 - P:Processor,处理器,一般 P 的数量就是处理器的核数,可以通过 GOMAXPROCS 进行修改。 本地隊列存放G
 - M:Machine,系统线程。默认数量限制是 10000
 - 流程:
 1. 调用 go func()创建一个goroutine;
2. 新创建的G优先保存在P的本地队列中,如果P的本地队列已经满了就会保存在全局的队列中;
3. M需要在P的本地队列弹出一个可执行的G,如果P的本地队列为空,则先会去全局队列中获取G,如果全局队列也为空则去其他P中偷取G放到自己的P中
4. G将相关参数传输给M,为M执行G做准备
5. 当M执行某一个G时候如果发生了系统调用产生导致M会阻塞,如果当前P队列中有一些G,runtime会将线程M和P分离,然后再获取空闲的线程或创建一个新的内核级的线程来服务于这个P,阻塞调用完成后G被销毁将值返回;
6. 销毁G,将执行结果返回
7. 当M系统调用结束时候,这个M会尝试获取一个空闲的P执行,如果获取不到P,那么这个线程M变成休眠状态, 加入到空闲线程中
- GM模型(舊)與GMP模型(新) 來源
 - GM缺點
 - 调度 : 获取G全局队列锁,形成了激烈的競争
 - 轉移 : P0執行G0生成G1 , 為了繼續執行G0需要轉移給P1執行 , 但G0和G1又共享資料
 - GPM:
 - 調度 : 因為多了P的本地隊列, 減少鎖競爭
 - 轉移 : P0執行G0生成G1 , G1优先存放到P0的本地队列中,如果队列满了,则会把P0队列中一半的G移动到全局队列
 - 如果P的本地队列为空,那么他会先到全局队列中获取G,如果全局队列中也没有G,则会尝试从其他线程绑定的P中偷取(steal)一半的G
 
- 效能調教工具 pyroscope
 - wget https://dl.pyroscope.io/release/pyroscope-0.31.0-linux-amd64.tar.gz
 - tar -zxvf pyroscope-0.31.0-linux-amd64.tar.gz
 - "github.com/pyroscope-io/pyroscope/pkg/agent/profiler"
 - profiler.Start(profiler.Config{
 - ApplicationName: "name",
 - ServerAddress: "address",
 - })
 - /tmp/pyroscope adhoc go run main.go
 - 效能調教工具 pprof
 - main.go
 - _ "net/http/pprof"
 - gorace()
 - func gorace() {
 - c := make(chan bool)
 - m := make(map[string]string)
 - go func() {
 - m["1"] = "a" // First conflicting access.
 - c <- true
 - }()
 - m["2"] = "b" // Second conflicting access.
 - <-c
 - for k, v := range m {
 - fmt.Println(k, v)
 - }
 - http.ListenAndServe("localhost:6060", nil)
 - }
 - 所有效能資訊
 - http://localhost:6060/debug/pprof/
 - cpu報告
 - go tool pprof http://localhost:6060/debug/pprof/profile
 - heap報告
 - go tool pprof http://localhost:6060/debug/pprof/heap
 - cli模式
 - top10 前10名
 - list [method] 查看method
 - pdf 匯出pdf
 - flat : func執行所需heap或cpu時間(不包含內部func所需時間)
 - cum : func所有所需heap或cpu時間
 - online分析報告
 - go tool pprof -http=:8080 C:\Users\david\pprof\pprof.alloc_objects.alloc_space.inuse_objects.inuse_space.003.pb.gz
 




