PHP中的算法基准是否毫无意义?

时间:2010-09-27 23:02:06

标签: php performance algorithm scripting-language

由于PHP对我来说比较简单,我希望在其中对算法进行基准测试以获得乐趣,并且我选择使用因子。

与迭代方法相比,当我达到80!时,递归函数的速度完全不及,并且当迭代有一条稳定的线时,递归函数逐渐飙升,实际上它是这样的(x =阶乘,y =秒):

http://i52.tinypic.com/2a9s7z4.png

但是在C / Java中(我刚刚实施了测试)显示相同的结果只能相互降低1-5%,速度几乎相同。

在脚本语言中以这种方式对算法进行基准测试是否无用?

编辑:对于NullUserException:

function factrec($x) {
    if($x <= 1) {
        return $x;
    } else {
        return $x * factrec($x - 1);
    }
}

7 个答案:

答案 0 :(得分:4)

在脚本语言中使用基准算法绝对没有意义。在做了基准测试之后,你会在PHP中使用哪个factorial实现? (假设由于某种原因你不能使用内置的那个。)

对于使用与您希望实现算法的功能明显不同的语言进行基准测试是毫无意义的。在这里,PHP中函数调用和if语句的相对成本显着地扭曲了结果(或者这是我最好的猜测)。如果你小心地理解为什么会这样,并避免它,它仍然可以是富有成效的:你会注意到差异将更加夸大。它归结为是否更容易用目标语言编写它或解决差异。

算法复杂性的简单计算应该足以决定使用哪一个,或者至少缩小选择范围。


正如Mike Axiak在评论中指出的那样,你甚至不在这里测试不同的算法,你正在测试同一算法的两种不同实现:将i上正在运行的产品从n保持到{ {1}}。使用与目标不同的语言执行此操作几乎总是毫无意义。

答案 1 :(得分:1)

在我看来,如果我要测试算法本身,我会选择C / C ++,以获得它在最佳条件下可以提供的“原始能力”。

另一方面,如果我必须选择哪种算法在某种条件下效果最好,我会尽量复制这种情况。它是否必须放在PHP应用程序中?让我们用PHP提供的结构在PHP中进行测试。是否需要使用STL容器?我将在这种情况下进行测试,而不仅仅是数组。在真实条件下进行IMHO测试是获得有意义结果的关键。得到这样的结果后,另一件好事就是调整这些条件(只要你可以在项目中改变它们)并看看你得到了什么效果,找到最佳条件 - 算法对。

答案 2 :(得分:1)

递归与迭代实现应该对特定算法的渐近行为没有实际影响。在某些语言(scala,Scheme,Lua,Standard ML,Mozart / Oz,erlang)中,实际上可以编写这两种语言来执行完全相同的语言。也就是说,以下方案代码:

(define factorial
  (lambda (n acc)
    (if (= n 0) acc
        (factorial (- n 1) (* n acc)))))
(factorial 5 1)
-> 120

不会使用堆栈,因此执行与迭代方法相同的操作。 (这称为尾调用优化,并在执行尾递归时以这种语言调用。)

答案 3 :(得分:1)

基准测试永远不会毫无意义。如果你有一些代码,用任何语言编写,对你的应用程序来说太慢了,你就会找出瓶颈。看看这些瓶颈,您需要寻找解决方案。一个解决方案可能使用不同的算法公式,甚至用不同的语言重写。

我不知道关于PHP的事情,所以我不知道在这种环境下递归是否得到了很好的处理,但我的印象是它不是实现重型重复数学的好选择...

答案 4 :(得分:1)

你因为递归不好而面临PHP的问题。人们通常不会选择PHP来做这件事。总是选择最适合这份工作的工具。

答案 5 :(得分:1)

考虑到练习的重点很有趣,不能毫无意义!但是试图让PHP执行递归计算可能表明您已准备好尝试使用函数式编程语言。你见过Haskell吗?尾调用优化,任何人?

来吧,加入黑暗面。

答案 6 :(得分:1)

Java和C比PHP快几个数量级 您需要显着增加输入大小才能看到结果。

此外,正如Aaron McSmooth所说,使用您计划使用的语言之外的其他语言对算法进行基准测试毫无意义。

我不确定,但我怀疑PHP会进行尾调用优化。 无论如何,使用尾递归函数应该可以提高递归函数的性能:

function factorial($n, $product) {
    if ($n < 1)
        return $product;
    else
        return factorial($n-1, $product*$n);
}

print(factorial(80, 1));