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   我和你并没有不同  阅读(294)  评论(0编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
历史上的今天:
2017-11-23 修改logstash的docker-entrypoint,实现配置文件的动态生成
< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示