Press "Enter" to skip to content

三元式(ternary)性能优化

PHP 5.4 由Arnaud 引入了一个对三元式的优化方案.
我们都知道PHP用写时复制来对变量复制做性能优化, 而在以前的三元式中, 却每次都会复制, 这在操作数是大数组的情况下, 会造成性能问题:

<?php
$a = range(1, 1000);
$i = 0;
$start = microtime(true);
while (++$i < 1000) {
    $b = isset($a)? $a : NULL;
}
var_dump(microtime(true) - $start);

相比, 我们采用if-else来做同样的功能:

<?php
$a = range(1, 1000);
$i = 0;
$start = microtime(true);
while (++$i < 1000) {
    if (isset($a)) {
        $b = $a;
    } else {
        $b = NULL;
    }
}
var_dump(microtime(true) - $start);

前者在我的机器上, 运行时间为: float(0.0448620319366), 而采用if-else则是: float(0.000280006027222)
为此, Arnaud提供了一个patch, 来对三元式做了一个优化, 使得三元式不会每次都复制操作数, 在优化以后, 开头给的例子的运行时间降低为: float(0.00029182434082031)

The ternary operator always copies its second or third operand, which is very
slow compared to an if/else when the operand is an array for example:
$a = range(0,9);
// this takes 0.3 seconds here:
for ($i = 0; $i < 5000000; ++$i) { if (true) { $b = $a; } else { $b = $a; } } // this takes 3.8 seconds: for ($i = 0; $i < 5000000; ++$i) { $b = true ? $a : $a; } I've tried to reduce the performance hit by avoiding the copy when possible (patch attached). Benchmark: Without patch: (the numbers are the time taken to run the code a certain amount of times) $int = 0; $ary = array(1,2,3,4,5,6,7,8,9); true ? 1 : 0 0.124 true ? 1+0 : 0 0.109 true ? $ary : 0 2.020 ! true ? $int : 0 0.103 true ? ${'ary'} : 0 2.290 ! true ?: 0 0.091 1+0 ?: 0 0.086 $ary ?: 0 2.151 ! ${'var'} ?: 0 2.317 ! With patch: true ? 1 : 0 0.124 true ? 1+0 : 0 0.195 true ? $ary : 0 0.103 true ? $int : 0 0.089 true ? ${'ary'} : 0 0.103 true ?: 0 0.086 1+0 ?: 0 0.159 $cv ?: 0 0.090 ${'var'} ?: 0 0.089 The array copying overhead is eliminated. There is however a slowdown in some of the cases, but overall there is no completely unexpected performance hit as it is the case currently.

不过, 还是要提醒下: PHP 5.4还处于开发阶段, 在最终release之前, 任何新特性都可能被调整或者更改. 如果大家有任何建议, 也欢迎反馈, 帮助我们使得PHP变得更好.
谢谢
更多更新信息, 请关注:Changelog

14 Comments

  1. 秋风
    秋风 May 7, 2013

    我在PHP5.4x下测试,三元比if还快些。但是PHP5.3x下测试,三元好慢!

  2. zerox
    zerox January 3, 2012

    原来这也是有差别的,颠覆了以前的认识啊。但还是喜欢三元式的简洁

  3. Jacky
    Jacky December 14, 2011

    这个优化很好很强大,我也发现这个问题,我都在考虑是不是全部要改成if/else来处理了。希望能早日出release版本。

  4. Iterse's blog
    Iterse's blog December 10, 2011

    三元运算很简洁,这个优化很有用..

  5. anythink
    anythink November 23, 2011

    哈哈 果然, 用if else 还是正解

  6. kkjames
    kkjames November 21, 2011

    To 6楼
    $b即使被用到也不代表会被写入,所以不一定有复制操作.

  7. 俺是乡下人
    俺是乡下人 November 17, 2011

    把isset($a)改成isset($a[$i]) 结果就不一样了

  8. 小蔡
    小蔡 November 6, 2011

    真是没想到呀

  9. willko
    willko November 4, 2011

    鸟哥,请教下。
    如果
    $a = bool ? $a : 1;
    这样 $a 每次都会赋值吗?

  10. CFC4N
    CFC4N November 4, 2011

    三元运算居然比if else 效率差,以前都没注意过。颠覆了我对三元运算的认识。

  11. mahone
    mahone November 4, 2011

    三元确实用的比较多,这个优化需要。。。学习了。。。

  12. 莫北
    莫北 November 4, 2011

    不太同意ls的观点,从这里来看确实是效率高好多,但是实际过程中$b总是会被使用的,到时候再复制的效率近乎就一样了,所以我太同意过分强调if/else代替三元操作这种简单的写法,降低代码的简洁性。。。

  13. 飞晏
    飞晏 November 4, 2011

    没想到此前三元运算的效率会比if/else差这么多
    三元运算代码中使用的非常多,这个优化还是很有用的

Comments are closed.