# Ternary operator performance improvements

- Thread: https://externals.io/message/55805
- Original archive: https://news-web.php.net/php.internals/55805
- Started by Arnaud Le Blanc on 2011-10-14T18:08:56+00:00
- Messages: 7
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #55805 — Arnaud Le Blanc — 2011-10-14T18:08:56+00:00

URL: https://externals.io/message/55805#55805

Hi,

I've already posted this patch and it has since been reviewed and improved. 
I'm re-posting it for discussion before eventually commiting it.

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.

What do you think ? Is there any objection ?

Best regards,

---

## #55806 — Dmitry Stogov — 2011-10-14T19:39:18+00:00

URL: https://externals.io/message/55805#55806 · In reply to: #55805

Hi,

As I already said, I don't see any technical issues with the patch.
I don't like it very mach, but it looks robust, and I don't object about it.

Thanks. Dmitry.


> Hi,
>
> I've already posted this patch and it has since been reviewed and improved.
> I'm re-posting it for discussion before eventually commiting it.
>
> 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.
>
> What do you think ? Is there any objection ?
>
> Best regards,

---

## #55839 — Ilia Alshanetsky — 2011-10-17T12:52:21+00:00

URL: https://externals.io/message/55805#55839 · In reply to: #55805

Seems like a good patch, +1 from me on inclusion into 5.4/HEAD.


> Hi,
>
> I've already posted this patch and it has since been reviewed and improved.
> I'm re-posting it for discussion before eventually commiting it.
>
> 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.
>
> What do you think ? Is there any objection ?
>
> Best regards,

---

## #55840 — Felipe Pena — 2011-10-17T12:57:05+00:00

URL: https://externals.io/message/55805#55840 · In reply to: #55839

2011/10/17 Ilia Alshanetsky <ilia@prohost.org>:
> Seems like a good patch, +1 from me on inclusion into 5.4/HEAD.
>
> 
> > […]
>
> --
> 
> 
>
>

+1 from me too.

-- 
Regards,
Felipe Pena

---

## #55842 — Alain Williams — 2011-10-17T13:07:30+00:00

URL: https://externals.io/message/55805#55842 · In reply to: #55805

> Hi,
> 
> I've already posted this patch and it has since been reviewed and improved. 
> I'm re-posting it for discussion before eventually commiting it.
> 
> 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:

Is that why the following does not work as I expected:

    $dbh = $how == 'r' ? (&$dbh_r) : (&$dbh_w);

$dbh is NOT a reference to $dbh_r or $dbh_w.

-- 
Alain Williams
Linux/GNU Consultant - Mail systems, Web sites, Networking, Programmer, IT Lecturer.
+44 (0) 787 668 0256  http://www.phcomp.co.uk/
Parliament Hill Computers Ltd. Registration Information: http://www.phcomp.co.uk/contact.php
#include <std_disclaimer.h

---

## #55861 — Arnaud Le Blanc — 2011-10-18T20:09:37+00:00

URL: https://externals.io/message/55805#55861 · In reply to: #55842

Hi,

Le Monday 17 October 2011 15:07:30, Alain Williams a écrit :
> 
> > […]
> 
> > […]
> Is that why the following does not work as I expected:
> 
>     $dbh = $how == 'r' ? (&$dbh_r) : (&$dbh_w);
> 
> $dbh is NOT a reference to $dbh_r or $dbh_w.

This is expected; 
http://docs.php.net/manual/en/language.operators.comparison.php explains it:

> Please note that the ternary operator is a statement, and that it doesn't 
evaluate to a variable, but to the result of a statement.

This is why you can't assign the result of the ternary operator by reference. 
The patch doesn't change this.

Best regards,

---

## #55865 — Stas Malyshev — 2011-10-18T21:47:43+00:00

URL: https://externals.io/message/55805#55865

Hi!


> It probably does, but it is quite subtle. I was expecting the above to work since
> it does in C -- although in C&variable is an address which can be used in an
> expression ... the PHP '&' operator is different, in spite of apparent similarities.

Actually, in PHP standalone & doesn't even make any sense. PHP has 
certain operations - assignment by reference (bind two names to one 
variable) and passing by reference (which is the same thing but 
cross-scope) and returning by reference (which again is the same thing 
but in opposite direction). But unlike C there's no operation "taking 
reference" because while C has pointers PHP doesn't have anything like 
that.
-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
