In [27]:
%%writefile slow_app.py
import sys
import time
def mock_download():
for i in range(5):
time.sleep(1)
def mock_database():
for i in range(20):
time.sleep(0.1)
def mock_calcate():
for i in range(100000000):
pass
def main():
mock_download()
mock_database()
mock_calcate()
if __name__ == "__main__":
sys.exit(main())
In [13]:
!time -p python slow_app.py
上面可以初步看到程序本身执行时间很短,大部分时间在等待写什么. 只能看到一个大概,不能定位到具体代码.
In [1]:
%%writefile timer.py
import time
class Timer(object):
def __init__(self, verbose=False):
self.verbose = verbose
def __enter__(self):
self.start = time.time()
return self
def __exit__(self, *args):
self.end = time.time()
self.secs = self.end - self.start
self.msecs = self.secs * 1000 # millisecs
if self.verbose:
print('elapsed time: %f ms', self.msecs)
In [2]:
from timer import Timer
with Timer() as t:
for i in range(1000000):
pass
print('elasped time %s s',t.secs)
可以将耗时写到日志里,这样在写代码的时候对关键的逻辑处(数据库、网络等)进行如上改写,然后通过分析日志排查性能问题. 当然也可以扩展一下将每次性能数据写入数据库分析.
line_profiler
可以分析每一行代码的执行耗时信息.
line_profiler
,使用pip install line_profiler
进行安装. 安装成功后可以看到叫做kernprof
的可执行程序.@profile
装饰器.(不需要显示import
任何模块,kernprof
会自动注入的)
In [28]:
%%writefile slow_app_for_profiler.py
import sys
import time
@profile
def mock_download():
for i in range(5):
time.sleep(1)
@profile
def mock_database():
for i in range(20):
time.sleep(0.1)
@profile
def main():
mock_download()
mock_database()
if __name__ == "__main__":
sys.exit(main())
In [29]:
!pip install line_profiler
In [30]:
!kernprof -l -v slow_app_for_profiler.py
-l
选项告诉kernprof
注入@profile
到脚本里. -v
告诉kernprof
显示执行结果到控制台.
Line #
:行号.Hits
: 这行代码运行次数.Time
: 这一行总耗时Per Hit
: 本行代码执行一次耗时.% Time
:本行耗时占总耗时(函数耗时)百分比.Line Contents
: 代码从结果可以很清楚的看到每一行的耗时, 这个对于一般的脚本很方便, 但是对于django
项目怎么办呢:
django-devserver
: 这个适合在开发环境发现一些性能问题,但是很多问题在线上才能发现. http://djangotricks.blogspot.com/2015/01/performance-bottlenecks-in-django-views.htmldjango-debug-toolbar
:yet-another-django-profiler
大概瞄了一眼django-devserver
使用的是LineProfiler
,我们可以在代码层面加入LineProfiler
.
memory_profiler
分析每一行内存消耗.
In [26]:
!pip install memory_profiler psutil
In [31]:
!python -m memory_profiler slow_app_for_profiler.py