Python SnakeViz 库

2024年8月29日 | 阅读 8 分钟

性能分析是一种重要的分析形式,我们可以利用它来分析代码的时间或空间复杂度。Python 等编程语言提供了各种库来满足性能分析的需求。一些用于分析时间复杂度的性能分析库的例子包括 cProfile、profile、line_profiler 等。一些用于分析空间复杂度的性能分析库的例子包括 memory_profiler、memprof、guppy/hpy 等。由 cProfile 等性能分析库生成的输出通常是带有多个行的日志文件,解释不同函数调用的利用时间。如果函数非常深且有许多代码行,那么分析此类日志文件可能会很乏味。

数据可视化是一个表示大量数据的过程。这些数据包含人眼可以捕捉到的不同模式,使我们能够更好地理解数据。Python 有一个名为 SnakeViz 的库,它可以接受 cProfile 库生成的性能分析文件并生成可视化。

了解 Python SnakeViz 库

SnakeViz 库是 Python 编程语言中 cProfile 模块输出的基于浏览器的图形查看器。它是利用标准库 pstats 模块的替代方案。SnakeViz 库最初受到 RunSnakeRun 的启发。该库可以在 Python 2.7 和 Python 3 上运行。SnakeViz 库仍然可能在 Python 2.6 上运行;但是,现在 Tornado 不再支持 Python 2.6,因此官方支持已停止。

SnakeViz 库包含两种可视化样式,用于可视化性能分析结果。

  1. 冰柱图
  2. 旭日图

冰柱图利用矩形的宽度来表示函数所花费的时间,而旭日图则利用弧的角度来表示函数所花费的时间。调用其他函数的函数将有一个特殊的子项,表示该函数在不包括其调用的其他函数的情况下所花费的时间。只有调用其他函数的函数才会有这样的子项。

如何安装 Python SnakeViz 库?

要安装 Python 库,我们需要 'pip',这是一个用于管理从受信任的公共存储库安装模块所需的包的框架。一旦我们有了 'pip',我们就可以使用 Windows 命令提示符 (CMD) 或终端中的命令来安装 snakeviz 库,如下所示。

语法

现在我们将通过不同的示例来理解 SnakeViz 库的用法。

基于 SnakeViz 的一些示例

现在让我们考虑一些基于 SnakeViz 库的示例。

示例 1:命令行/Shell 中的 SnakeViz

以下示例演示了 SnakeViz 库的用法。在此示例中,我们将调用 mainFunction(),它将调用三个函数并逐个打印所有函数返回的结果。所有三个函数都类似,每个函数都生成 1-150 之间的 150000 个随机数并返回该数字的平均值。唯一不同的是每个函数所花费的时间。我们将手动引入一个计时器,该计时器将暂停每个函数不同的时间。我们将借助 cProfile 库来分析此脚本,然后利用 SnakeViz 可视化输出。

文件:exampleOne.py

输出

# we will utilize the following command to profile exampleOne.py
$ python -m cProfile -o exampleOne.prof exampleOne.py
75.36921333333333
75.40457333333333
75.51178

# we can then call the below command to launch SnakeViz
# visualization in the browser
$ snakeviz exampleOne.prof
# Once we execute the above command, the SnakeViz library will launch
# visualization on a browser

说明

在上面的代码片段中,我们导入了所需的模块。然后,我们定义了 verySlowRandomGenerator、slowRandomGeneratorfastRandomGenerator 等函数来生成类似的输出。在这些函数中,我们还包含了 time 模块的 sleep() 方法,其值不同,这有助于我们区分每个函数所花费的时间。然后,我们定义了 mainFunction() 函数,我们在其中打印了上述定义函数的返回值。最后,我们调用了 mainFunction() 函数。

在上面的录屏中,我们可以看到 SnakeViz 库默认生成了两个图表,我们可以从下拉列表中更改图表。性能分析的所有单独行都将在下面的可视化表中显示。

  1. 冰柱图: 冰柱图使用矩形来表示函数所花费的时间。mainFunction() 矩形内的函数,如 fastRandomGenerator、slowRandomGeneratorverySlowRandomGenerator,会显示它们的矩形。我们可以进一步单击其中任何函数的矩形,它将被设置为根矩形,并且其中调用的所有子函数将显示在它下方作为矩形。这些矩形以一种树状结构组织,其方式是它们被调用的顺序,并且矩形的宽度代表该函数在其调用函数中花费的时间。我们可以看到脚本总共消耗了约 8.38 秒。
  2. 旭日图: 旭日图使用弧的角度来表示函数所花费的时间。我们可以以与冰柱图相同的方式看到,mainFunction() 弧的范围内显示了 fastRandomGenerator、slowRandomGeneratorverySlowRandomGenerator 的弧。我们可以单击任何弧,该弧将成为根弧,并且其中调用的函数将显示在其周围的弧中。

现在我们将了解可视化中的不同组件,它们可以帮助我们更好地理解可视化。

  1. 函数信息: 我们可以将鼠标悬停在冰柱图的矩形或旭日图的弧上,它将在左侧显示它所代表的函数的详细信息。它将显示函数名、累积时间、函数所在文件、调用时的行号以及文件目录。
  2. 调用堆栈: 调用堆栈按钮位于右上角。它用于表示调用堆栈。如果我们单击任何矩形或弧,图表会将该节点设置为根节点,并且所有子节点将显示其中调用的函数。它将带我们深入到该函数。如果我们深入到多个函数,逐个分析它们,并且想知道堆栈路径,我们可以单击 调用堆栈 按钮,它将显示调用堆栈。我们还可以单击其中的任何条目,它将带我们到该级别。
  3. 统计表: 统计表cProfile 生成的输出相同。它将显示在图表中。统计表中的每一行都是可点击的,代表函数调用,并且每当我们单击某一行时,该行将成为图表的根节点,并且其中调用的所有函数将显示为子节点。
  4. 重置根节点: 如果我们通过单击统计表中的行更改了图表根节点,那么我们可以单击此按钮将根节点重置为原始状态。
  5. 重置缩放: 如果我们通过单击任何矩形或弧进行了性能分析的缩放,那么我们可以通过单击此按钮进行重置。
  6. 样式: 样式有两个选项,对应于两种图表类型
    1. 冰柱
    2. 旭日
  7. 深度: 深度下拉菜单允许我们选择 SnakeViz 在创建可视化时深入到调用堆栈的多少层。我们可以增加性能分析的深度,并且一次会在图表中显示许多层。低于此深度的调用将不会在图表中显示,除非我们单击其中一个顶层函数。
  8. 截断: 截断下拉菜单允许我们决定是否显示占其父项累积时间非常短时间比例的函数的调用。如果我们设置一个较高的截断值,图表将生成得更快,因为许多子图表将不会被生成。如果比例小于截断值,则该函数将被显示;但是,对于该函数内的子函数将不会构建图表,这意味着我们无法再单击该函数来查看其中消耗的子函数时间。

示例 2:Jupyter Notebook 中的 SnakeViz

我们也可以轻松地在 Jupyter notebook 中使用 SnakeViz 库。首先,我们需要将 SnakeViz 库作为扩展加载到 notebook 中,然后我们可以调用 snakeviz 作为行或单元格魔术命令。

让我们考虑以下语法将 SnakeViz 库加载为扩展。

语法

现在让我们使用与上一个示例相同的代码;但是,我们将使用 %snakeviz 行命令来调用 mainFunction(),以生成其 SnakeViz 可视化。它将在 notebook 中生成可视化。

文件:exampleTwo.py

输出

75.41503333333333
75.59046666666667
75.37472
 
*** Profile stats marshalled to file '/tmp/tmps5uyxuux'. 
Embedding SnakeViz in this document...
# this will return the SnakeViz visualization

说明

在上面的代码片段中,我们使用了前一个示例的代码。然后,我们使用了 %snakeviz mainFunction() 语句来调用函数并为其生成 SnakeViz 可视化。

示例 3

现在让我们考虑以下示例,其中我们将使用相同的代码再次生成 SnakeViz 可视化;但是,这次我们将使用 %%snakeviz 单元格魔术命令来解释其用法。

文件:exampleThree.py

输出

75.67562666666667
75.38932
75.47096666666667
 
*** Profile stats marshalled to file '/tmp/tmphty5rhzv'. 
Embedding SnakeViz in this document...
# this will return the SnakeViz visualization

说明

在上面的代码片段中,我们使用了 %%snakeviz 单元格魔术命令,并重复了前一个示例的代码片段。