返回信息流最近写了一个与udp传输有关的程序,规模不大不小,1600+行,其它都工作顺利,但cpu占用却一直异常,查了好几天也无法定位。
其实之前还有内存占用的问题,但通过sigQuit查看退出时的函数栈发现了一些未按预期关闭的goroutine,基本解决了内存问题,但cpu占用问题却一直有,即使看Quit时并无多余的goroutine
请问各位一般都如何debug这种问题,有什么好用的方法或者工具吗?
-------------------------------------
[更新]感谢大家的热心支招,困扰了我不止两周的问题终于解决了。至于我期间有多抓狂,看看我现在编辑帖子时间就知道了!
**万恶之源:time 定时器**
同时这也是一个完全可避免的故事,如果当时上点心。因为我曾经很早以前瞟到过time中的说明
- be aware that without a way to shut it down the underlying Ticker cannot be recovered by the garbage collector; **it "leaks".**
it leaks...但是当时没往心里去。所以我在程序中使用的time.NewTicker()没有Stop……想当然地以为既然是局部变量,那么会被自动回收的,然后,结局大家都知道了:cpu缓慢增长,但并没有goroutine异常,内存也看不出问题……
感觉大家推荐pprof,虽然结果总是runtime在占用cpu,一度让我无从下手,一开始以为是chan使用不佳导致竞争过多,但始终无果,甚至开始怀疑golang……但我还是一直在改再重新prof+google,周末两天就这么过去了。。。顺带把把一些原本性能不高的代码又优化了一通。
最后,功夫不负有心人,或者说瞎猫死耗子,大量blog中遇到一个提及timer的,顺手一查我又再次看到了上面那段原话,这回,顿悟真相的我眼泪掉下来
“it leaks”,误解了引号的意思啊,以为是夸张,结果是强调。。。
这是一条镜像帖。来源:北邮人论坛 / golang / #496同步于 2016/7/26
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Golang机器人发帖
[Solved]如何定位异常的cpu占用
AzYet
2016/7/26镜像同步22 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
能想到的关键地方都已经加了日志,目前没有发现异常。
cpu占用是缓慢累积的,要运行比较久才有明显上升,比如一两个小时,感觉有可能是异常情况没有处理好。
而且是udp网络程序,每个包都会走一遍流程,都加日志,量会非常大,可读性很低。所以才想问有没有更有效的方法
【 在 nuanyangyang 的大作中提到: 】
: 程序有日志吗?如果CPU占用量很大,说明总有线程在跑着。如果到处都有日志,就会发现大量的打印才对。
【 在 AzYet 的大作中提到: 】
: 能想到的关键地方都已经加了日志,目前没有发现异常。
: cpu占用是缓慢累积的,要运行比较久才有明显上升,比如一两个小时,感觉有可能是异常情况没有处理好。
: 而且是udp网络程序,每个包都会走一遍流程,都加日志,量会非常大,可读性很低。所以才想问有没有更有效的方法
: ...................
进程中的goroutine数目有没有变化呢?(可能是goroutine没有死导致的。不知道SigQuit准不准,毕竟操作系统的信号,里面很微妙的。你的程序有没有办法统计活的“奴隶”线程的数量)
另外你的服务器是什么风格的?是select/poll/epoll风格的吗?会不会程序中用了什么算法,复杂度是O(n^2)的?(可能是描述符(各种各样的描述符)数量过多,使得仅仅是“等待一个请求”这样的简单的任务也要轮询大量的描述符)
另外,网络流量有没有随着CPU占用率增加而增加?(有没有可能是网络协议实现不善,产生了ping-pong这种现象?
关于OS的风格问题,我完全不懂,不过排查了这么久之后,确实有点怀疑是否其它原因了,刚好看一看学习一下。
服务器是CentOS
【 在 nuanyangyang 的大作中提到: 】
:
: 进程中的goroutine数目有没有变化呢?(可能是goroutine没有死导致的。不知道SigQuit准不准,毕竟操作系统的信号,里面很微妙的。你的程序有没有办法统计活的“奴隶”线程的数量)
: 另外你的服务器是什么风格的?是select/poll/epoll风格的吗?会不会程序中用了什么算法,复杂度是O(n^2)的?(可能是描述符(各种各样的描述符)数量过多,使得仅仅是“等待一个请求”这样的简单的任务也要轮询大量的描述符)
: ...................
看看你这个程序有多少线程在跑,用top或者htop,看看同时run的task有多少;
不行用pprof,查一下就好了,很好的性能观测工具,go语言自带。
thx,晚上找个时间看看pprof
【 在 YiYeShu 的大作中提到: 】
: 看看你这个程序有多少线程在跑,用top或者htop,看看同时run的task有多少;
: 不行用pprof,查一下就好了,很好的性能观测工具,go语言自带。