GIL 确保 Python 进程一次只能执行一条指令
====分析工具
cProfile 分析函数耗时
ncalls:表示函数调用的次数;
tottime:表示指定函数的总的运行时间,除掉函数中调用子函数的运行时间;
percall:(第一个percall)等于 tottime/ncalls;
cumtime:表示该函数及其所有子函数的调用运行的时间,即函数开始调用到返回的时间;
percall:(第二个percall)即函数运行一次的平均时间,等于 cumtime/ncalls;
filename:lineno(function):每个函数调用的具体信息;
python -m cProfile -s tottime your_program.py=========import cProfile
cp=cProfile.Profile()
cp.enable()
#中间是你想测的函数
cp.disable()
cp.print_stats()
火焰图
pip install flameprof
import cProfile # 把需要 profile 的代码放到 pr.enable 和 pr.disable 中间if __name__ == '__main__':
pr=cProfile.Profile()
pr.enable() # 开始收集性能分析数据
main()
pr.disable() # 停止收集性能分析数据
pr.dump_stats("/statistic/pipe1.prof") # 把当前性能分析的内容写入一个文件
flameprof pipe1.prof> pipe1.svg
针对 Python 可以尝试:cProflile + gprof2dot 而针对 Go 可以使用: pprof + go-torch
if __name__ == "__main__""test()")
# 把分析结果保存到文件中
cProfile.run("test()", filename="result.out")
# 增加排序方式
cProfile.run("test()", filename="result.out", sort="cumulative")
适用面命令行的方式:
# 直接把分析结果打印到控制台
python-m cProfile test.py
# 把分析结果保存到文件中
python-m cProfile -o result.outtest.py
# 增加排序方式
python-m cProfile -o result.out -s cumulative test.py
python提供了一个pstats模块,用来分析cProfile输出的文件内容
import pstats
# 创建Stats对象
p= pstats.Stats("result.out")
# strip_dirs(): 去掉无关的路径信息
# sort_stats(): 排序,支持的方式和上述的一致
# print_stats(): 打印分析结果,可以指定打印前几行
# 和直接运行cProfile.run("test()")的结果是一样的
p.strip_dirs().sort_stats(-1).print_stats()
=============
line_profiler 逐行分析
heapy 追踪 Python 内存中所有的对象— 这对于消灭奇怪的内存泄漏特别有用
memory_profiler 图的形式展示 RAM 的使用情况随时间的变化
虽然它们不支持改变大小,但是我们可以将两个元组合并成一个新元组。任意两个元组相加始终返回一个新分配的元组,所以复杂度是O(n)
>>> t1 = (1,2,3,4)
>>> t2 = (5,6,7,8)
>>> t1 + t2
(1, 2, 3, 4, 5, 6, 7, 8)
#coding:utf8fromflask import Flask, jsonify
import timefromfunctools import wrapsfromline_profiler import LineProfiler
#查询接口中每行代码执行的时间
def func_line_time(f):
@wraps(f)
def decorator(*args, **kwargs):
func_return= f(*args, **kwargs)
lp=LineProfiler()
lp_wrap=lp(f)
lp_wrap(*args, **kwargs)
lp.print_stats()returnfunc_returnreturndecorator19app=Flask(__name__)
@app.route('/line_test')
@func_line_time
def line_test():for item in range(5):
time.sleep(1)for item in xrange(5):
time.sleep(0.5)return jsonify({'code':200})if __name__=='__main__':
app.run()
fromline_profiler import LineProfiler
import random
def do_stuff(numbers):
s=sum(numbers)
l= [numbers[i]/43 for i inrange(len(numbers))]
m= ['hello'+str(numbers[i]) for i inrange(len(numbers))]
numbers= [random.randint(1,100) for i in range(1000)]
lp=LineProfiler()
lp_wrapper=lp(do_stuff) #zcy装饰
lp_wrapper(numbers) # zcy传参
lp.print_stats() #zcy调用
import time
from line_profiler import LineProfiler
def tst(age):
print('tst stst')
time.sleep(1)
print('age',age)
def idokown(name):
print('i love u',name)
time.sleep(2)
i=9*2-4
print(i)
tst(12)
if __name__ == '__main__':
lp = LineProfiler()
lp.add_function(tst) #若没这句话,则在分析结果中没有对tst函数的分析
lp_wrapper = lp(idokown) #装饰idokown
lp_wrapper('zzz') #调用idokown
lp.print_stats() #直接打印结果
# lp.dump_stats('pp.out') 将结果保留到一个文件中
# python3 -m line_profiler pp.out 打印文件中的内容