往期回顾:
本期看点(技巧类用【技】表示,易错点用【易】表示):
(1)pprof查看运行时状态信息【技】
(2)goruntine使用后的销毁【易】
PS:《Go语言开发小技巧&易错点100例》算上这一篇已经完成了20篇啦!五分之一!继续加油
正文如下:
pprof是Go语言的性能分析工具,主要可以分析以下几种情况:
运行代码:
package main
import (
"fmt"
"net/http"
_ "net/http/pprof"
"strings"
)
func main() {
http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
writer.Write([]byte("Hello~"))
})
http.ListenAndServe(":9090", nil)
}
访问链接:http://localhost:9090/debug/pprof/
在上节我们学到了如何去控制goruntine的数量,因为短时间内大量的goroutine同时执行也会造成内存崩溃、CPU占用率过高等问题,不仅如此,当goruntine启动后未进行关闭时,因为大量的挤压goroutine也会造成相同的问题,因此我们要习惯在项目中使用goruntine后进行关闭。
代码示例:
package main
import (
"fmt"
"net/http"
_ "net/http/pprof"
)
func main() {
ints := make(chan int,1000)
i := 0
worker := func (ch chan int){
for v := range ch {
fmt.Println(v)
}
}
http.HandleFunc("/go", func(writer http.ResponseWriter, request *http.Request) {
i+=1
ints<-i
go worker(ints)
})
http.ListenAndServe(":9090", nil)
}
查看pprof:
我们发现同一个地方我们只go出去一次,但是几次请求后还是有很多goruntine,这样如果大批量请求的话一定会出问题。
第一种优化方式,就是换一种方式去监听channel:
package main
import (
"fmt"
"net/http"
_ "net/http/pprof"
)
func main() {
ints := make(chan int,1000)
i := 0
worker := func (ch chan int){
select {
case v := <-ch:
fmt.Println(v)
default:
return
}
}
http.HandleFunc("/go", func(writer http.ResponseWriter, request *http.Request) {
i+=1
ints<-i
go worker(ints)
})
http.ListenAndServe(":9090", nil)
}
第二种方式,我们可以close掉channel来间接的关闭监听他的goruntine
package main
import (
"fmt"
"net/http"
_ "net/http/pprof"
)
func worker(v ...int) {
count := len(v)
res :=make(chan int,count)
go func (ch chan int){
for i := 0; i < count; i++ {
fmt.Println(v[i])
ch <- v[i]
}
}(res)
for i := 0; i < count; i++ {
<-res
}
close(res)
}
func main() {
val := 0
http.HandleFunc("/go", func(writer http.ResponseWriter, request *http.Request) {
val += 1
go worker(val)
})
http.ListenAndServe(":9090", nil)
}
第三种方式,使用Context机制关闭多余的goruntine