python高性能编程 读书笔记

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__":  #参考:https://blog.csdn.net/asukasmallriver/article/details/74356771
    import cProfile

    # 直接把分析结果打印到控制台
    cProfile.run("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.out test.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:utf8
from flask import Flask, jsonify
import time
from functools import wraps
from line_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() 
        return func_return 
    return decorator 
19 
app = 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()
from line_profiler import LineProfiler 
import random
 
def do_stuff(numbers):
    s = sum(numbers)
    l = [numbers[i]/43 for i in range(len(numbers))]
    m = ['hello'+str(numbers[i]) for i in range(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 打印文件中的内容

 








 

 

posted on 2019-11-23 20:44  我和你并没有不同  阅读(290)  评论(0编辑  收藏  举报