这是我参与「第五届青训营 」伴学笔记创作活动的第 10 天
这是我参与「第五届青训营 」伴学笔记创作活动不水的第 1 天
在写极简抖音的聊天模块时,频繁使用到channel和select-case.在第一次尝试运行时,我的clash崩了,浏览器也崩了,我以为只是普普通通的内存吃满,毕竟浏览器开了20+页面,我的轻薄本带不动时家常便饭.但是,但是,我发现任务管理器的数据:CPU100%,内存70%.我意识到这可不是内存的问题,再往下翻main.go占CPU60%.我想到我参考的代码中有多处select被我改了,我怀疑是自己改错了.于是我打开了pprof......
首先,gin框架使用pprof需要导入包,注册路由:
package main
import (
"github.com/gin-contrib/pprof"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
pprof.Register(router)
router.Run(":8080")
}
使用命令,go tool pprof http://localhost:8080/debug/pprof/profile,在pprof命令行下,
打入"top",打入"png":
问题代码是这样的:如果channel没有东西的话,ok返回false,而!ok直接continue,那么相当于进入一个for死循环......这样cpu就吃满了.
for {
select{
case msgContent,ok := <-c.MsgChan:
if !ok {
continue
}
msgData := S2CMsgData{
FromUserId: c.UserId,
MsgContent: string(msgContent),
}
msg, _ := json.Marshal(msgData)
_ = c.Conn.WriteMessage(websocket.TextMessage, msg)
}
}
于是,我改成了:
for {
select{
case msgContent:= <-c.MsgChan:
msgData := S2CMsgData{
FromUserId: c.UserId,
MsgContent: string(msgContent),
}
msg, _ := json.Marshal(msgData)
_ = c.Conn.WriteMessage(websocket.TextMessage, msg)
}
}
top,png:
淦,依然吃满...而且主要开销在json上,我就很奇怪,难道说依然是死循环了,而且死循环的同时走了一遍序列化???,我最后把代码改成:
for {
select{
case msgContent,ok := <-c.MsgChan:
if !ok {
_ = c.Conn.WriteMessage(websocket.CloseMessage, []byte{})
return
}
msgData := S2CMsgData{
FromUserId: c.UserId,
MsgContent: string(msgContent),
}
msg, _ := json.Marshal(msgData)
_ = c.Conn.WriteMessage(websocket.TextMessage, msg)
}
}
top,png:
这个start函数是我的监听ws的函数,合理. 终于cpu降到了10%,危机解除.