【问题标题】:Difference between Benchmarking and Profiling基准测试和分析之间的区别
【发布时间】:2016-04-20 11:44:40
【问题描述】:

我看到 software benchmarkingprofiling 这两个术语有时可以互换使用,但就我的理解而言,存在细微差别。

两者都按时间连接。但是,基准测试主要是关于确定可以与其他应用程序进行比较的某个速度得分,而分析可以为您提供有关应用程序花费大部分时间(或周期数)的确切信息。

对我来说总是这样:集成测试是基准测试的对应物,单元测试是分析的对应物。但是微基准测试如何适应这一点?

有人说here

分析和基准测试是同一枚硬币的两面,分析可以帮助您缩小到最有用的优化范围,基准测试可以让您轻松隔离优化并交叉比较它们。

另一个人说here关于Profiling:

分析在不同的时间意味着不同的东西。有时这意味着衡量绩效。有时这意味着诊断内存泄漏。有时这意味着了解多线程或其他低级活动。

那么,这些技术在概念上是不同的还是不是非黑即白?

【问题讨论】:

    标签: profiling benchmarking


    【解决方案1】:

    个人资料示例

    import cProfile
    import re
    cProfile.run('re.compile("foo|bar")')
    

    输出

        197 function calls (192 primitive calls) in 0.002 seconds
    
    Ordered by: standard name
    
    ncalls  tottime  percall  cumtime  percall filename:lineno(function)
         1    0.000    0.000    0.001    0.001 <string>:1(<module>)
         1    0.000    0.000    0.001    0.001 re.py:212(compile)
         1    0.000    0.000    0.001    0.001 re.py:268(_compile)
         1    0.000    0.000    0.000    0.000 sre_compile.py:172(_compile_charset)
         1    0.000    0.000    0.000    0.000 sre_compile.py:201(_optimize_charset)
         4    0.000    0.000    0.000    0.000 sre_compile.py:25(_identityfunction)
       3/1    0.000    0.000    0.000    0.000 sre_compile.py:33(_compile)
    

    https://docs.python.org/3.10/library/profile.html?highlight=profile#module-profile

    分析器模块旨在为给定程序提供执行配置文件

    出于基准测试的目的,timeit 以获得相当准确的结果。

    这尤其适用于针对 C 代码对 Python 代码进行基准测试:分析器 为 Python 代码引入开销,但不适用于 C 级函数(不公平!),等等C 代码似乎比任何 Python 代码都快。

    cProfile 推荐给大多数用户;它是一个具有合理 开销 的 C 扩展,使其适合分析 长时间运行的 程序。基于 lsprof

    【讨论】:

      【解决方案2】:

      基准是衡量某些整个操作的时间的东西。例如在某些工作负载下每秒的 I/O 操作。所以结果通常是一个数字,以秒或每秒操作数为单位。或者一个包含不同参数结果的数据集,以便您可以绘制它。

      您可以使用基准来比较不同硬件上的相同软件,或与您的基准交互的其他软件的不同版本。例如使用不同的 apache 设置对每秒最大连接数进行基准测试。


      分析的目的不是比较不同的事物:它是关于了解程序的行为。 配置文件结果可能是每个函数所用时间的表格,或even per instruction with a sampling profiler。您可以说它是配置文件而不是基准,因为说“该功能花费的时间最少,因此我们将保留该功能并停止使用其余功能”是没有意义的。

      阅读维基百科文章以了解更多信息:https://en.wikipedia.org/wiki/Profiling_(computer_programming)

      您使用配置文件来确定要优化的地方。在你的程序花费 99% 的时间的函数中加速 10% 比在任何其他函数中加速 100% 更有价值。更好的是,您可以改进您的高级设计,从而减少调用昂贵的函数,并使其更快。


      微基准测试是一种特定形式的基准测试。这意味着您正在测试一个超级具体的东西,以单独衡量它,而不是任何真正有用的东西的整体性能。

      微基准测试结果示例:

      非微基准测试结果示例:

      • 使用 7-zip(使用特定选项和硬件)压缩这 100MB 的文件集合需要 23 秒。
      • 在某些硬件/软件组合上编译 Linux 内核需要 99 秒。

      另见https://en.wikipedia.org/wiki/Benchmark_(computing)#Types_of_benchmarks

      微基准测试是基准测试的一种特殊情况。如果你做得对,它会告诉你哪些操作是昂贵的,哪些是便宜的,这有助于你尝试优化。如果你做错了,你甚至可能根本没有测量你打算测量的东西。例如您编写了一些 C 来测试循环与 while 循环,但是编译器出于不同的原因制作了不同的代码,您的结果毫无意义。 (对于现代优化编译器来说,表达相同逻辑的不同方式几乎无关紧要;不要在这上面浪费时间。)微基准测试很难。

      另一种判断它是微基准的方法是,您通常需要查看编译器的 asm 输出,以确保它正在测试您希望它测试的内容。 (例如,它没有通过从循环中提升一些昂贵的东西来优化重复 1000 万次循环的迭代,这些东西应该重复整个操作足够的次数以提供可以准确测量的持续时间。)

      微基准测试可能会扭曲事物,因为它们会使用热缓存和已启动的分支预测器来测试您的函数,并且它们不会在调用被测代码之间运行任何其他代码。这可以使巨大的循环展开看起来不错,当作为实际程序的一部分时,它会导致更多的缓存未命中。同样,它使大查找表看起来不错,因为整个查找表最终都在缓存中。完整的程序通常会在调用函数之间弄脏足够的缓存,以至于查找表并不总是在缓存中命中,因此仅计算一些东西会更便宜。 (大多数程序都受内存限制。重新计算不太复杂的东西通常和查找一样快。)

      【讨论】:

      • 感谢您抽出宝贵时间。但我的困惑始于微基准测试——这是否意味着我只是 benchmark 我的程序的某个功能?而与 profile 某个功能的区别究竟是什么?
      • @JimMcAdams:是的,这正是微基准测试的全部内容:多次重复相同的工作。在配置文件结果中,深入到单个函数有望逐行显示总时间的百分比。 (或逐条指令,因为在这种粒度下,asm 的外观比源更重要。)或者您可以分析记录缓存未命中而不是时钟周期。
      • 很好的答案,(我正在努力学习如何把事情解释得足够清楚)你练习过教学吗? :)。
      • @0xc0de。是的,我喜欢分享我的知识,无论是在我的许多(长而详细的 :) SO 答案中,还是在玩 Ultimate [frisbee] 或其他东西时。
      【解决方案3】:

      通常人们进行分析不是为了衡量程序的速度,而是为了找出如何让它更快。

      通常他们这样做的假设是,通过测量特定函数或代码行所花费的时间来最好地发现速度。

      有一个明确的方法来考虑这个问题:如果一个函数或代码行显示了一个包含百分比的时间,这就是如果该函数或代码行可以节省的时间的一部分可以使代码花费零时间(通过不执行或将其传递给无限快的处理器)。

      除了函数或代码行之外,还有其他需要时间的事情。 这些是程序正在做什么的描述,但它们不是唯一的描述。

      假设您运行一个分析器,每 N 秒的实际时间(不仅仅是 CPU 时间)收集一个程序状态样本,包括调用堆栈和数据变量。 调用堆栈不仅仅是一堆函数名称——它是调用这些函数的调用站点的堆栈,通常是参数值。 然后假设您可以检查并描述其中的每一个。

      例如,对样本的描述可以是:

      • 例程 X 正在分配内存,以便在必要时通过例程 Q 初始化用于记录患者的字典。

      • 程序正在读取一个 dll 文件,目的是提取一个字符串资源,该资源位于调用堆栈的几个级别,将用于填充进度条中存在的文本字段以告知用户为什么程序需要这么长时间:)

      • 程序正在使用某些参数调用函数 F,并且它之前使用相同的参数调用过它,并给出了相同的结果。这表明人们可以只记住先前的结果。

      • 程序正在调用函数 G,而函数 G 正在调用函数 H 的过程中,只是为了破译 G 的参数选项标志。程序员知道这些标志总是相同的,这表明特殊版本的 G 可以节省时间。

      • 等。等等

      这些是可能的描述。 如果它们占 F% 的时间,那就是每个样本满足该描述的概率。 更简单的描述是:

      • 例程或代码行 X 出现在 Q% 的堆栈样本上。这是衡量的包容性百分比
      • 例程 D 在 R% 的堆栈样本上立即出现在例程 E 的上方。该数字可以放在从 D 到 E 的调用图的弧上。
      • 堆栈序列 main->A->B->C->D->E 是出现在样本数最多的序列。这就是“热门路径”。
      • 最常出现在堆栈底部的例程是 T。这是“热点”。

      大多数分析器工具只为您提供这些简单的描述。 一些程序员了解自己检查样本的价值,因此他们可以对程序花费时间的原因进行更多的语义描述。 如果目标是准确测量由于特定描述而导致的时间百分比,则必须检查大量样本。 但是,如果描述出现在 少量 样本中的很大一部分上,则说明没有准确测量它,但知道 它很大,并且它已经 准确地找到了。 看到不同? 您可以权衡测量的准确性以换取加速发现的能力。

      这就是random pausing背后的原理,统计上的理由是here

      【讨论】:

        【解决方案4】:

        基准测试可以帮助您观察系统在负载下的行为, 确定系统的容量,了解哪些变化是重要的,或者 查看您的应用程序如何处理不同的数据。

        剖析是衡量和分析时间的主要手段 被消耗。分析需要两个步骤:测量任务和时间 经过,并对结果进行汇总和排序,以使重要的 任务冒泡到顶部。 --High performance MySQL

        我的理解是:benchmark 是了解您的应用程序的方法,而 profiling 是改进您的应用程序的方法。

        【讨论】:

        • 感谢您抽出宝贵时间。所以微基准测试意味着你会稍微了解你的应用程序?但是这样做有什么好处呢?
        • 我认为微基准测试意味着您将了解您的应用程序的特定方面或关键点,而不仅仅是一点点。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-07
        • 2023-03-05
        • 2014-09-18
        • 1970-01-01
        • 1970-01-01
        • 2017-11-08
        • 1970-01-01
        相关资源
        最近更新 更多