是否应该测试算法复杂度?如果是这样,怎么办?


14

假设我正在实现一些简单的操作,例如搜索排序的列表/数组。该函数(在c#中)看起来类似于:

static int FindIndex(int[] sortedList, int i);

我可以根据功能来实现和测试它,但是出于显而易见的原因,我通常宁愿二进制搜索胜于线性搜索或某些故意的愚蠢行为。

所以我的问题是:我们是否应该尝试编写能够在算法复杂度方面保证性能的测试,如果可以,如何做?

我已经开始在这个问题的“您应该”部分的两边都进行争论,但是我想看看人们在没有我的争论的情况下会怎么说。

就“如何”而言,这变得非常有趣:)您可以看到参数化比较运算符并进行测试,该测试的比较运算符对比较进行计数或类似的操作。但是仅仅因为你能做并不意味着你应该...

有没有其他人考虑过(可能)?谢谢。


@steenhulthin-我将在这里慢炖,然后检查一下。我从来没有去过那里。
SirPentor 2011年

顺便说一句,好问题。+1
拉斐尔·科鲁奇

Answers:


13

算法复杂度是一种理论构造,因此最好使用铅笔和纸进行“测试”。无法对其进行有效的机械测试。

绝对性能可以进行机械测试,并可以进行有用的单元测试。如果性能很重要,则可以指定一个阈值:“此查询在10 6个数字上运行不超过50 毫秒,在10 7个数字上运行不超过60毫秒。” 您可以为其建立单元测试。

最终用户不在乎您的算法是线性算法还是对数算法。他们关心的是,即使在应用程序中存储了一年的数据后,UI是否仍会立即响应。


这也是我的本能。但是,让我思考的是框架上的性能保证时。示例:如果我没记错的话,stl在算法复杂度方面有一些保证(可以在此处关闭)。
SirPentor 2011年

仅仅因为库提供了某些保证并不意味着它们必须是可单元测试的。
2011年

@Tobias Brick:测试和定义某些东西是两件事。
DeadMG 2011年

演示性能很难。它涉及许多用于变化参数的采样点。当各个功能无关紧要时,它会更容易,但除此之外... ...您的负载,RAM,前端总线速度,CPU,内核数,编译器的积极性,注册表的污染程度都将影响特定程序的运行时间样品。
工作

3

虽然我不确定该工具是否对单元测试特别有用,但Goldsmith,Aiken和Wilkerson 的论文“ Empirical Computational Complexity”描述了一种检测代码的方法,并根据一组各种输入来观察代码的动态行为,以凭经验进行研究。得出其渐近复杂度。本文中描述的程序是开源的,可在此处获得

希望这可以帮助!


0

最主要的是尝试使用大数据,看看是否花费太长时间。

以我的性能调优经验为例例如在某个算法为(例如)O(n ^ 2)的情况下,只要它所花费的时间百分比永远不会进入雷达,就可能很好。

但是,如果给定的数据集大小可能每年都看不到,但是每年一次,则该算法占用的总时间中的一部分可能会变成灾难性的优势。

如果您可以在测试中做到这一点,那将是一件非常好的事情,因为发现问题非常容易,就像它是一个实际的无限循环一样。


0

我认为您不想做的是单元测试。

AFAIK,单元测试仅是为了确保代码能够完成应做的工作,并且不会关注性能。

来自Wikipedia:不能期望测试能够捕获程序中的每个错误:除了最琐碎的程序之外,不可能评估所有执行路径。单元测试也是如此。另外,根据定义,单元测试仅测试单元本身的功能。因此,它不会捕获集成错误或更广泛的系统级错误(例如跨多个单元执行的功能,或诸如性能之类的非功能测试区域)。单元测试应与其他软件测试活动结合进行。像所有形式的软件测试一样,单元测试只能显示错误的存在。他们不能显示没有错误。

还有其他类型的工具和模式可以用来衡量绩效。我现在记得的其中一项是针对非功能需求的验收测试

性能测试(使用压力测试,负载测试等)很少。

您还可以将一些压力工具与构建工具(ant,自动构建工作室)一起使用,作为部署步骤的一部分(这就是我的工作)。

因此,简短的答案是“否”,在单元测试代码时,您不必担心。


0

传递比较器并跟踪它的调用次数仅出于简单的目的,例如在固定输入(例如new int[] { 1,2,3, ... , 1024 })中进行搜索时检查比较数是否保持在10以下。至少明确说明算法的行为意图。

我认为单元测试不是验证您的算法为O(log n)的正确方法;这将需要大量的随机数据生成,一些曲线拟合以及可能粗糙的统计数据来确定一堆数据点是否适合预期的运行时间。(对于此算法,它可能是可行的,但是如果您开始进行排序等操作,将很难反复遇到最坏的情况)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.