使用火焰图定位cpu性能问题是一种实用的手段,可以简单的从火焰图中看出性能的瓶颈点,cpu火焰图有on cpu off cpu 两种模式。前些日子发现有个python的性能问题需要分析,于是搜到profiler_online这个开源项目生成on cpu火焰图

安装

pypi
pip install profiler_online
源码安装
git clone https://github.com/rfyiamcool/profiler_online.git
cd profiler_online
python setup.py install

用法

在项目引入:

1
2
3
4
from gevent import monkey
from profiler_online import run_profiler
monkey.patch_all()
run_profiler()

run_profiler支持三个参数:

1
2
3
4
5
6
debug_config = {
'host': '127.0.0.1',
'port': 8080,
'tmp_path: '/tmp/debug'
}
run_profiler(**debug_config)

测试

打开浏览器 http://127.0.0.1:8080 或者wget http://127.0.0.1:8080,这样就可以显示正在运行服务的性能火焰图了.

profiler_online收集堆栈代码分析

profiler_online是通过signal.setitimer这个函数间隔0.005s收集一次堆栈 然后使用FlameGraph把堆栈的使用频率汇总并生成火焰图展示到浏览器web上面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
def start(self):
self._started = time.time()
try:
signal.signal(signal.SIGVTALRM, self._sample)
except ValueError:
raise ValueError('Can only sample on the main thread')
signal.setitimer(signal.ITIMER_VIRTUAL, self.interval, 0)
def _sample(self, signum, frame):
stack = []
while frame is not None:
stack.append(self._format_frame(frame))
frame = frame.f_back
stack = ';'.join(reversed(stack))
self._stack_counts[stack] += 1
signal.setitimer(signal.ITIMER_VIRTUAL, self.interval, 0)#interval=0.005
def _format_frame(self, frame):
return '{}({})'.format(frame.f_code.co_name,
frame.f_globals.get('__name__'))

其他python性能分析方式

Python 优化第一步: 性能分析实践
里面提到了vprof这个火焰图工具,这个比profiler_online强大不少,不仅可以收集cpu火焰图还可以收集内存火焰图,代码执行时间等,收集的粒度比profiler_online细了不少,不过相对的影响的性能也大了些。 本来想写vprof的,不过生成出来的火焰图太难用了~