代码之家  ›  专栏  ›  技术社区  ›  KaptajnKold

进行TDD时的性能测试最佳实践?

  •  9
  • KaptajnKold  · 技术社区  · 16 年前

    我正在做一个急需性能调整的项目。

    如果我的优化没有提高程序的速度,如何编写一个失败的测试?

    详细说明一下:

    问题不在于发现哪些部分需要优化。为此,我可以使用各种分析和基准测试工具。

    问题是使用 自动化的 用于记录特定优化确实具有预期效果的测试。如果我以后可以使用测试套件来发现可能的性能回归,那也是非常理想的。

    我想我可以运行我的分析工具来获取一些值,然后断言优化后的代码产生了更好的值。然而,这方面的明显问题是,基准价值观不是硬价值观。它们因当地环境而异。

    那么,总是使用同一台机器进行这种集成测试的答案是什么呢?如果是这样,您仍然需要考虑结果中的一些模糊性,因为即使在相同的硬件上,基准测试的结果也可能有所不同。那么如何考虑这一点呢?

    或者也许答案是保留旧版本的程序并比较前后的结果?这将是我首选的方法,因为它主要是环境不可知的。有人有这种方法的经验吗?我想只有在最新版本的性能至少和前一个版本一样好的情况下,如果所有的测试都能通过,才有必要保留一个旧版本。

    9 回复  |  直到 9 年前
        1
  •  5
  •   Carl Manaster    16 年前

    我怀疑将TDD应用于驾驶性能是一个错误。无论如何,使用它来获得好的设计和工作代码,并使用在TDD过程中编写的测试来确保持续的正确性——但是一旦您有了良好的分解代码和一套可靠的测试,您就可以很好地进行调整,并应用不同的(与TDD不同的)技术和工具。

    TDD为您提供了良好的设计、可靠的代码和测试覆盖安全网。这让你进入了一个很好的调谐位置,但我认为,由于你和其他人提到的问题,它不会带你在调谐的道路上走得更远。我是TDD的忠实拥护者和实践者。

        2
  •  3
  •   Ed Guiness    16 年前

    首先需要为可接受的性能建立一些标准,然后需要设计一个在使用现有代码时会使该标准失败的测试,然后需要调整代码的性能,直到它通过测试。您可能会有多个性能标准,您当然应该有多个测试。

        3
  •  3
  •   Dan    16 年前

    在许多服务器应用程序(可能不是您的情况)中,性能问题只在并发访问和负载下出现。因此,测量一个程序执行的绝对时间并试图改进它并不是很有帮助。即使在单线程应用程序中,此方法也存在问题。测量绝对常规时间依赖于平台提供的时钟,这些是 not always very precise ;你最好依赖于日常生活所需的平均时间。

    我的建议是:

    • 使用分析来确定执行次数最多、花费时间最多的例程。
    • 使用类似工具 JMeter Grinder 为了详细说明有代表性的测试用例,模拟并发访问,让您的应用程序处于压力之下,并测量(更重要的)吞吐量和平均响应时间。这将使您更好地了解从外部角度看,您的应用程序是如何运行的。

    虽然您可以使用单元测试来建立应用程序的一些非功能性方面,但我认为上面给出的方法在优化过程中会给出更好的结果。在单元测试中放置与时间相关的断言时,您将不得不选择一些非常近似的值:时间可能因您运行单元测试所使用的环境而异。你不希望测试失败仅仅是因为你的一些同事在使用劣质的硬件。

    调音就是找到合适的调音对象。您已经有了一个正常工作的代码,因此放置与性能相关的断言 后验 如果不建立关键的代码段,可能会导致您在优化应用程序的非关键部分上浪费大量时间。

        4
  •  2
  •   Rik elirevach    16 年前

    记录当前代码的运行时间。

    if (newCode.RunningTime >= oldCode.RunningTime) Fail
    
        5
  •  1
  •   eglasius    16 年前

    在ci服务器中运行tests+profiling。您还可以定期运行负载测试。

    您关心的是差异(正如您所提到的),所以这不是定义绝对值。有一个额外的步骤来比较这次运行和最后一次构建的性能度量,并将差异报告为%。你可以对时间的重要变化提出警告。

    如果你关心的是绩效,你应该有明确的目标,你想达到并坚持他们。你应该用整个系统的测试来衡量。即使您的应用程序逻辑很快,您也可能会遇到视图问题,导致您无法达到目标。您也可以将其与差异方法相结合,但对于这些方法,您对时间变化的容忍度会降低。

    请注意,您可以在开发人员计算机中运行相同的进程,只使用该计算机中以前的运行,而不是开发人员之间的共享运行。

        6
  •  0
  •   Matthew Farwell    16 年前

    对于优化本身,可以直接比较旧代码和新代码。但不要把两份都放在身边。这听起来像是一场噩梦。而且,你只会比较一个版本和另一个版本。功能上的改变可能会减慢您的功能,这是用户可以接受的。

    就我个人而言,我从未见过“必须比上一个版本快”类型的性能标准,因为它很难度量。

    你说“非常需要性能调整”。哪里?哪些问题?哪些功能?谁说,企业,用户?什么是可接受的性能?3秒?2秒?50毫秒?

    任何性能分析的起点都是定义通过/失败标准。一旦有了它,就可以自动执行性能测试。

    为了提高可靠性,可以使用(简单的)统计方法。例如,在相同条件下运行相同的查询100次。如果95%的人在N秒内返回,那就是通过。

    就我个人而言,我将在集成时从标准机器或集成服务器本身执行此操作。在某个地方记录每个测试的值(巡航控制对这类事情有一些很好的功能)。如果这样做,您可以看到性能随着时间的推移以及每次构建的进展情况。你甚至可以做一个图表。经理们喜欢图表。

    在进行性能测试时,无论是否进行自动化测试,都很难有一个稳定的环境。无论你如何开发(tdd、瀑布等),你都会遇到这个特殊的问题。

        7
  •  0
  •   Gishu    16 年前

    还没有面对这种情况;)不过,如果我这样做了,我会这样做。(我想我是从戴夫·阿斯特尔的书中找到的)

    步骤1:为“可接受的性能”制定一个规范,例如,这可能意味着“用户需要在N秒(或毫秒)内完成Y”
    步骤2:现在编写一个失败的测试。使用友好的计时器类(例如net有秒表类)和 Assert.Less(actualTime, MySpec)
    第三步:如果测试已经通过,你就完成了。如果是红色,则需要优化并使其变为绿色。一旦测试进入绿色,性能现在是“可接受的”。

        8
  •  0
  •   Ramkrishna    13 年前

    Kent Beck和他的团队自动化了TDD中的所有测试。

    对于性能测试,我们也可以在tdd中自动化测试。

    性能测试的标准是我们应该测试是或否的情况

    如果我们很好地了解这些规范,我们也可以在tdd中实现自动化。

        9
  •  0
  •   Community CDub    8 年前

    虽然我大体上同意卡尔·马纳斯特的回答,但使用现代工具是有可能的 一些 TDD为功能测试和性能测试提供的优势。

    使用大多数现代性能测试框架(我的大部分经验是 Gatling ,但我相信大多数性能测试框架的较新版本也是如此),可以将自动性能测试集成到持续集成构建中,并对其进行配置,以便在性能需求不满足时,ci构建将失败。

    因此,如果可以事先就您的性能需求达成一致(对于某些应用程序,这可能是由与用户或客户达成一致的sla驱动的),这可以在更改导致性能问题时为您提供快速反馈,并确定需要性能改进的方面。

    良好的性能要求是这样的:“当每小时有5000个订单时,95%的用户行程应该包括不超过10秒的等待,以及不超过1秒的屏幕切换”。

    这还依赖于在ci管道中部署到类似于生产的测试环境。

    然而,使用性能需求驱动开发的方式可能仍然不是一个好主意,就像使用功能需求一样。对于功能性需求,在运行应用程序之前,您通常会对它是否会通过测试有一些了解,并且尝试编写您认为会通过的代码是明智的。在表演上, trying to optimize code whose performance hasn't been measured is a dubious practice . 你可以使用性能 结果 在某种程度上推动应用程序开发,而不是性能 要求 .