这个系统的存在是解决大量并发数据库查询的问题,主体思路是通过LRU算法缓存结果信息和请求合并来实现的一个数据缓存和请求削峰服务,从而大量减少直接的数据库连接查询并将查询效率也大大提高。
在系统刚调试完成,请求正确处理的那一刻内心是激动的,然后当服务开启之后,习惯性的查看了下功耗,内存使用正常,CPU却在眼下不断增高,2%-5%-10%-20%-50%-80%-100%,在短短几分钟就飙到了100%。。。内心是崩溃的,此时刚从一堆代码中缕顺流程。呢,如何快速的定位到问题?我应该从哪些方面下手,或者说我应该查看哪些数据来推测所有的可能性?究竟是哪个package,哪个函数甚至是哪一行代码影响了它的性能?
3.此时只有pprof了,查看程序的运行时数据。。。
好吧,这是一个有意思的事情,golang大法好,稍微修改了几行代码,开启pprof接口查看运行时cpu数据和heap数据。
首先,收集下CPU的信息,看看谁在占着我的cpu
p>
从上面的截图可以看出flat%最高的是rumtime.mach_semaphore_signal方法,在这里只有28%左右其实更高,达到60+%(此图截错了,罢了,罢了,在此说明问题就行)。Ok,知道了到底是什么导致的CPU高,下面我们追溯下代码路径,在此我使用火焰图来分析,更加直观。
从火焰图我们可以很方便的分析各个方法占用的CPU的时间。
它是SVG格式的,鼠标放上去还能看细节。Y轴是栈的深度,X轴是所有的采样点的集合,每个方框代表一个栈帧(stack frame)。 颜色没有意义,只是随机的选取的。左右顺序也不重要。看的时候可以从最宽的帧看起,从底往上看,帧上的分叉代表不同的代码路径。快速识别和量化的CPU使用率
从火焰图的信息可以看到,在整个cpu占用信息采集过程中几乎全部都是runtime的信息,并且是runtime.timerproc。通过分析go语言的源码我们可以知道这是一个定时器调度goruntine。(代码是go1.7.3源码,我经过了裁剪,保留大意)
调度流程分析如下: