如何测试自己写的函数程序慢在哪里
前言
在开发过程中,优化程序性能是一项至关重要的任务。尤其是在处理大量数据或复杂算法时,找出程序中的瓶颈对于提高效率至关重要。本文将介绍如何使用 line_profiler 这一强大的工具来定位 Python 函数中的耗时点。通过具体的例子,我们将演示如何安装和使用 line_profiler,并展示它如何帮助我们识别并优化那些导致程序运行缓慢的部分。
安装
!pip install line_profiler -i https://pypi.mirrors.ustc.edu.cn/simple/
Looking in indexes: https://pypi.mirrors.ustc.edu.cn/simple/
Collecting line_profiler
Downloading https://mirrors.ustc.edu.cn/pypi/packages/82/ad/06f4321260d709c5503bff79a41141b5725e3a1055151649ccbace98f663/line_profiler-4.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (718 kB)
[2K [90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[0m [32m718.1/718.1 kB[0m [31m4.8 MB/s[0m eta [36m0:00:00[0ma [36m0:00:01[0m
[?25hInstalling collected packages: line_profiler
Successfully installed line_profiler-4.1.3
运行测试程序
测试程序为之前编写的计算经纬度距离的函数,已放入 project 中
!head /home/mw/project/test.py
你需要做的仅仅是在函数前增加一个装饰器@profiler
eee
!kernprof -l -v test.py
Distances (first few elements):
[[ 3159.18918786 14643.10185207 7650.32449848 8573.73083237
12650.20642209]
[ 7037.54644113 3080.23896724 14975.47890911 11841.96330602
8743.0463527 ]
[10295.70808389 7033.29073201 4083.76761385 19282.7567062
18171.59151038]
[ 2907.8340534 9900.53032942 13261.30789668 9773.43351035
7203.35265715]
[13257.5275834 6853.12299363 11334.78737952 19004.35542823
11065.46618589]]
Wrote profile results to test.py.lprof
Timer unit: 1e-06 s
Total time: 0.000883144 s
File: test.py
Function: haversine at line 3
Line # Hits Time Per Hit % Time Line Contents
==============================================================
3 @profile
4 def haversine(lat1, lon1, lat2, lon2, R=6371):
5 # 将角度转换成弧度
6 1 77.2 77.2 8.7 lat1_rad, lon1_rad = np.radians(lat1), np.radians(lon1)
7 1 71.2 71.2 8.1 lat2_rad, lon2_rad = np.radians(lat2), np.radians(lon2)
8
9 # 计算差值
10 1 32.6 32.6 3.7 dLat = lat2_rad - lat1_rad
11 1 27.7 27.7 3.1 dLon = lon2_rad - lon1_rad
12
13 # Haversine 公式
14 1 585.7 585.7 66.3 a = np.sin(dLat / 2.0)**2 + np.cos(lat1_rad) * np.cos(lat2_rad) * np.sin(dLon / 2.0)**2
15 1 84.9 84.9 9.6 c = 2 * np.arctan2(np.sqrt(a), np.sqrt(1 - a))
16
17 # 返回距离
18 1 3.8 3.8 0.4 return R * c
运行之后会发现 project 目录多了一个文件,是分析结果的记录
/home/mw/project/test.py.lprof
可以用以下语句查看
```python
!python -m line_profiler test.py.lprof
Timer unit: 1e-06 s
Total time: 0.000883144 s
File: test.py
Function: haversine at line 3
Line # Hits Time Per Hit % Time Line Contents
==============================================================
3 @profile
4 def haversine(lat1, lon1, lat2, lon2, R=6371):
5 # 将角度转换成弧度
6 1 77.2 77.2 8.7 lat1_rad, lon1_rad = np.radians(lat1), np.radians(lon1)
7 1 71.2 71.2 8.1 lat2_rad, lon2_rad = np.radians(lat2), np.radians(lon2)
8
9 # 计算差值
10 1 32.6 32.6 3.7 dLat = lat2_rad - lat1_rad
11 1 27.7 27.7 3.1 dLon = lon2_rad - lon1_rad
12
13 # Haversine 公式
14 1 585.7 585.7 66.3 a = np.sin(dLat / 2.0)**2 + np.cos(lat1_rad) * np.cos(lat2_rad) * np.sin(dLon / 2.0)**2
15 1 84.9 84.9 9.6 c = 2 * np.arctan2(np.sqrt(a), np.sqrt(1 - a))
16
17 # 返回距离
18 1 3.8 3.8 0.4 return R * c
从提供的 line_profiler 输出来看,我们可以清楚地看到函数 calculate_qv_divergence 中每一行代码的执行时间。下面是对关键数据点的分析:
最耗时的部分是在 ha 公式的主要计算上 (Line # 14),占用了总执行时间的 64.7%。
转换纬度和经度为弧度 (Line # 6 和 Line # 7) 也消耗了一定的时间,分别占用了总执行时间的 8.8% 和 8.7%。
计算大圆弧的中心角 (Line # 15) 占用了总执行时间的 10.3%。。
执行上述代码后,line_profiler 将输出每个函数调用的时间统计信息。通过观察这些统计数据,我们可以发现哪些行或哪些部分消耗了最多的时间,从而找到优化的目标。
小结
通过使用 line_profiler,我们能够轻松地识别出程序中耗时较长的部分。这对于优化代码执行效率非常有用,特别是在处理大型数据集或执行密集型计算时。在实践中,我们建议定期使用这类工具来审查代码,以便及时发现并解决性能问题
参考链接:https://www.cnblogs.com/fnng/p/14702535.html
https://www.jianshu.com/p/a06a715b5a52