背景1
天下武功,为快不破!
上学的时候,有些人考试半小时就已经把卷子写完了。有些人还没写完。
工作的时候,有些人一天就能把活干完了,有些人还没开始。
写论文的时候,有些人代码都写完了,数据都处理好的,有些人连论文题目都没看。
学习的时候,有些人,1年内学到了不少知识。一年快过去了,有些人还没开始。
吃饭的时候,有些人都去吃饭了,有些人还在说:“我把这局(游戏)打完奥”。
生命的长度是有限的
不要浪费时间~
一切都要速度!
因为这个公众号的缘故
经常有一些人来加我微信,然后我就可以看到各种各样的朋友圈内容。
比如某某某,在朋友圈发了一个照片,照片上是一个电脑进度条,显示代码还需要几百个小时才能跑完。文本配的又非常自信,觉得自己的代码要运行几百个小时,自己实在是太牛了。
我就纳闷了,你什么数据,处理需要几百个小时?
我真的看不出来,你哪来的自信,怎么就不知道优化一下你的代码呢?代码需要跑那么久,真的没发现有什么问题嘛?
背景2
现在分析讲究的是定量分析
比如分析公司的时候,要看这个公司的财报数据。
分析中国股市的时候,会看上证指数等。
查看一个人是否发烧,要看体温计的数值。
一个田径运动员,会关注他跳的有多远,跑的有多快,都是通过高度和速度来衡量的。
一个人的成绩好坏,是通过他的考试成绩分数来判断的。
so
那么,我是一个工程师,而且是一个爱写代码的工程师,我要求我写的代码足够快!快到无人打败!
而作为衡量代码运行的速度,就是统计代码中每一个函数的运行时间。
找到那些拖后腿的函数(耗时长的函数),然后想办法优化它。
正文
那么,如何去检测python中每一个函数的运行时间呢?
而且,怎么直观的展示出来?让人一目了然的发现问题?
这个方法不难,看完本文你就知道。
代码
我们创建一个模拟人生的代码,创建一个文件code120701.py
,填写下面的代码:
from tqdm import tqdm
import time
import random
class Person:
def __init__(self, name: str,) -> None:
self.name = name
def _sleep(self) -> None:
time.sleep(random.randint(8, 10)/24)
def _eat(self) -> None:
time.sleep(random.randint(3,4)/24)
def _study(self) -> None:
time.sleep(random.randint(6,9)/24)
def _entertainment(self) -> None:
time.sleep(random.randint(5, 6)/24)
def _day(self) -> None:
self._study()
self._entertainment()
self._eat()
self._sleep()
def _life(self, days:int=30) -> None:
_ = [self._day() for i in tqdm(range(days))]
def main():
p = Person(name="统计学人")
p._life()
if __name__ == "__main__":
main()
可以看出来,上面代码,就是模拟了一个人一天的基本时间分配。
- 吃
- 睡
- 学习
- 娱乐
每一个行为的需要的时间都是随机的。但是整体上占比都是固定的。
正常运行
通常,我们运行python代码,可能就是这样的
python code122701.py
这样当然可以。就是普通的运行模式
计时运行
如果你希望给你的代码每一个函数都计算时间的话,你需要这么运行:
python -m cProfile -o profile120701.prof code122701.py
一起来看一下,这个相当于正常运行
,多了几个部分.我们把上面那句话拆解一下:
python
:就是调用python软件-m cProfile
:表示额外调用python内置性能评估包cProfile
-o profile120701.prof
:表示输出这个上面代码
的成绩单
,一定要注意格式哦-o 成绩单名称.prof
code122701.py
:就是你的代码名称。
可视化
上面的成绩单,已经都放在profile120701.prof
里面了。但是直接让我们看,看的也不清楚呀。
不如一个图看的清楚。
为了让成绩单看的更加清楚,需要使用snakeviz
包来渲染。
如果没安装这个包,要先安装一下:pip install snakeviz
然后再使用snakeviz
来查看上面的成绩单
,怎么看呢?
这么运行即可:
snakeviz ./profile120701.prof
然后就会自动打开浏览器,就可以看到这个页面。
阅读
首先来看第一张截图
- 在冰柱可视化样式中,函数由矩形表示。 根函数是最顶层的矩形,下面是它调用的函数,然后是下面调用的函数,依此类推。 在函数内花费的时间量由矩形的宽度表示。 横跨大部分可视化的矩形表示一个函数占用了其调用函数的大部分时间,而细长的矩形表示一个函数几乎没有使用任何时间。
- 左边几个按钮,可以随便点击,选择自己喜欢的样式,只要能帮助你定位问题即可。
- 如果不小心下钻到自己都不知道的位置,点击
reset zoom
即可。 - 实在不行,就筛选网页页面。
再看第二张截图
- 第二张图是一个表格。主要是了解每一列的意义.
ncalls
:调用函数的总数。如果有两个数字,则表示函数递归,第一个是调用总数,第二个是原始(非递归)调用的次数.totttime
:在函数中花费的总时间,不包括调用子函数花费的时间.percall
:tottime
除以ncalls
.cumtime
:在这个功能和所有子功能上花费的累计时间.percall
:cumtime
除以ncalls
.filename:lineno(function)
: 定义函数的文件名和行号,以及函数名.
总结
-
如果想看详细介绍,可以点击它的官网查看:
https://jiffyclub.github.io/snakeviz/ -
sankeviz
其实还支持jupyter notebook
,可惜的是vscode版本的jupyter
不能用。
-
snakeviz
也就是把cprofile
输出的结果给可美化了一下,更好看了。 -
还有很多别的性能分析的包,推进大家去看看,但是我觉得大部分会用一个就足够了。
防杠声明
(上面列举的各种情况,只是为了举例子,请勿对号入座,如果发现说的就是你,那就是你了)
最后
后面将会写更多有用的、有意思的文章
如果你也喜欢python、喜欢编程、热爱生活、积极向上、喜欢废话连篇
那就关注、点赞、收藏我文章
我是【统计学人】