龙空技术网

Python:使用cProfile对代码段进行性能分析

Doobi姐姐 122

前言:

现在姐妹们对“c语言代码分析工具怎么用”可能比较讲究,看官们都想要剖析一些“c语言代码分析工具怎么用”的相关知识。那么小编在网摘上搜集了一些关于“c语言代码分析工具怎么用””的相关内容,希望小伙伴们能喜欢,你们一起来了解一下吧!

当尝试优化缓慢的函数或模块时,通过性能分析可以更好地了解代码的性能瓶颈。在Python中,可以使用cProfile模块对代码进行快速的性能分析。下面是两个不同版本的代码片段,可用于对代码段进行性能分析。这些代码片段改编自cProfile文档中的“Profile”示例。多年来,我一直使用这些代码片段来缩小性能问题的范围。

基本版本

此版本适用于对模块级别代码进行性能分析。将以下两个代码块粘贴到目标代码周围:

import cProfile, pstatsprofiler = cProfile.Profile()profiler.enable()...profiler.disable()pstats.Stats(profiler).sort_stats(pstats.SortKey.CUMULATIVE).print_stats(100)

第一个代码块创建并启动性能分析器。第二个代码块停止它并打印前100个函数,按累积调用时间排序。

例如,对一些类定义进行性能分析:

from django.db import modelsimport cProfile, io, pstatsprofiler = cProfile.Profile()profiler.enable()class DanceKind(models.IntegerChoices):    FANDANGO = 1    TANGO = 2class Dance(models.Model):    kind = models.IntegerField(choices=DanceKind.choices)profiler.disable()out = io.StringIO()pstats.Stats(profiler).sort_stats(pstats.SortKey.CUMULATIVE).print_stats(100)

当模块导入时,您将看到来自print_stats()调用的输出:

$ python manage.py shell      18305 function calls (17540 primitive calls) in 0.044 secondsOrdered by: cumulative timeList reduced from 552 to 100 due to restriction <100>ncalls ... cumtime  percall filename:lineno(function)  97/2 ...   0.044    0.022 {built-in method builtins.__build_class__}     1 ...   0.043    0.043 /.../django/db/models/base.py:95(__new__)     6 ...   0.043    0.007 /.../django/db/models/base.py:369(add_to_class)     1 ...   0.043    0.043 /.../django/db/models/options.py:175(contribute_to_class)     1 ...   0.043    0.043 /.../django/utils/connection.py:14(__getattr__)     1 ...   0.043    0.043 /.../django/utils/connection.py:56(__getitem__)     1 ...   0.043    0.043 /.../django/db/utils.py:191(create_connection)     1 ...   0.043    0.043 /.../django/db/utils.py:103(load_backend)     1 ...   0.043    0.043 /.../importlib/__init__.py:108(import_module)   2/1 ...   0.043    0.043 <frozen importlib._bootstrap>:1192(_gcd_import)...

表格显示了函数的调用情况,以文件名、行号和名称为标识。它们按累积时间(“cumtime”)排序,即在该函数中花费的总时间(包括其被调用方),按最长时间优先排序。

请注意,如果两个代码块之间的代码段引发异常,则性能分析器将继续运行。通常不用担心这个问题,因为模块级别的异常通常会停止程序。

以下是已润色的文章:

上下文管理器和装饰器版本

这个版本适用于对函数或函数部分进行分析。通过使用 @contextlib.contextmanager​,它既可以用作上下文管理器,也可以用作装饰器。

首先,将以下定义粘贴到目标模块中:

from contextlib import contextmanager@contextmanagerdef profile_and_print():    import cProfile, pstats    profiler = cProfile.Profile()    profiler.enable()    try:        yield    finally:        profiler.disable()    pstats.Stats(profiler).sort_stats(pstats.SortKey.CUMULATIVE).print_stats(100)

通过使用 try/finally​,如果发生异常,分析器将始终处于禁用状态。只有在成功时才会打印配置文件,尽管您可以通过缩进最后一行来更改此设置。

要将其用作函数装饰器:

from django.shortcuts import renderfrom example.models import Dance...@profile_and_print()def index(request):    context = {        "top_dancers": get_top_dancers(),        "total_dances": Dance.objects.count(),    }    return render(request, "index.html", context)

以及作为上下文管理器:

def index(request):    context = {        "top_dancers": get_top_dancers(),        "total_dances": Dance.objects.count(),    }    with profile_and_print():        return render(request, "index.html", context)

在任一情况下,运行分析代码块将再次为该部分打印分析结果:

      4092 function calls (4012 primitive calls) in 0.008 secondsOrdered by: cumulative timeList reduced from 376 to 100 due to restriction <100>ncalls ... cumtime  percall filename:lineno(function)     1 ...   0.008    0.008 /.../django/shortcuts.py:17(render)     1 ...   0.007    0.007 /.../django/template/loader.py:52(render_to_string)     1 ...   0.006    0.006 /.../django/template/loader.py:5(get_template)...
可能的调整

以下是您可能想要修改此段代码的几种方式。

排序

要按其他指标排序,请使用从 此表 中选择 SortKey.CUMULATIVE​ 之外的其他值。最有用的是:

​SortKey.TIME​,用于大多数内部时间,即在函数内部花费的时间,不包括对其他函数的调用。最慢的函数通常是优化的易发现目标。​SortKey.CALLS​,用于调用次数。可能有方法可以消除重复的函数调用,例如使用缓存。显示

默认情况下,Stats​ 类将输出到标准输出。要输出到标准错误,请在创建时传递 stream=sys.stderr​:

pstats.Stats(profiler, stream=sys.stderr).sort_stats(    pstats.SortKey.CUMULATIVE,).print_stats(100)

要保存到文件,请将 print_stats()​ 替换为 dump_stats()​:

pstats.Stats(profiler).sort_stats(    pstats.SortKey.CUMULATIVE,).dump_stats("profile.stats")

您可以使用可视化工具(如 tuna)使用此文件。

总结

在Python中,使用 cProfile 模块可以快速进行性能分析,以了解代码的性能问题。这篇文章提供了两个版本的代码片段,一个适用于对模块级别代码进行性能分析,另一个适用于对函数或函数部分进行性能分析。您可以按照代码片段的指示将其粘贴到目标代码周围,然后运行并查看分析结果。分析结果将按照累积调用时间排序,并且可以根据需要进行排序和显示。性能分析器将始终处于禁用状态,只有在成功时才会打印配置文件。

标签: #c语言代码分析工具怎么用