php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #67124 Typecast (bool) $array slowdown according to array length
Submitted: 2014-04-24 03:09 UTC Modified: 2014-08-27 10:01 UTC
Votes:2
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: vovan-ve at yandex dot ru Assigned: dmitry (profile)
Status: Closed Package: Performance problem
PHP Version: Irrelevant OS: Linux
Private report: No CVE-ID: None
 [2014-04-24 03:09 UTC] vovan-ve at yandex dot ru
Description:
------------
Casting non-empty array to boolean using (bool) takes a time with respect to array length. There are no reasons for this. This is abnormal.

Any other checks like `if ($array)`, `($array) ?:`, `[] === $array` and so on are not affected.

At least whole PHP 5 is affected by this issue.

Test script:
---------------
$tests = array(
    '$empty' => array(),
    '$full'  => range(1, 1000),
);
$count = 1 * 1000 * 1000;

foreach ($tests as $name => $array) {
    printf("%-10s", $name);

    $start = microtime(true);

    $i = $count;
    while ($i-- > 0) {
        (bool) $array;
    }

    $total = microtime(true) - $start;
    printf("%6.2F sec. total\n", $total, $total / $count);
}

Actual result:
--------------
$empty      0.15 sec. total
$full      52.03 sec. total

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-04-24 03:55 UTC] vovan-ve at yandex dot ru
More clear test cases:

    $tests = array(
        'empty' => array(),
        'x10'   => range(1, 10),
        'x100'  => range(1, 100),
        'x1000' => range(1, 1000),
    );

Result:

    empty       0.15 sec. total
    x10         0.65 sec. total
    x100        5.14 sec. total
    x1000      49.91 sec. total
 [2014-04-24 04:47 UTC] vovan-ve at yandex dot ru
Looks like array is copied while casting:

    # memory_limit=1G

    echo "Create array...";
    $array = array_fill(0, 10 * 1000 * 1000, null);
    echo " ok\nCasting...";
    $start = microtime(true);
    (bool) $array;
    printf(" %.3F sec.\n", microtime(true) - $start);

Output:

    Create array... ok
    Casting...Fatal error: Allowed memory size of 1073741824 bytes exhausted (tried to allocate 35 bytes) in ...
 [2014-04-26 09:43 UTC] hanskrentel at yahoo dot de
The workaround is to first count with arrays as the count is cached.

(bool) count($array);
 [2014-04-26 12:59 UTC] vovan-ve at yandex dot ru
Yes, "workaround" to pass thru the bugs maze. Welcome to PHP. Did you expect something else?..
 [2014-04-27 07:19 UTC] hanskrentel at yahoo dot de
Workaround to get the timings low in the test-script only. And I didn't meant that in a positive fashion. A workaround is always crap and expensive.

However, as internally it might be easy to get the array value count, the internal function that so far converts array into boolean could be optimized by looking for such array count instead of iterating through it.

And yes I did expect something else. I was quite astonished how expensive the bool cast is with arrays with more than 100 members. I didn't know that so far. I always expected casts to be quick, I hope this gets fixed.
 [2014-04-29 10:10 UTC] johannes@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: dmitry
 [2014-04-29 10:10 UTC] johannes@php.net
Yes, the guess is correct - we copy the array, then "convert" the copy see  ZEND_CAST opcode handler http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_operators.c#511
I don't see an obvious way to improve this without duplicating the conversion logic. You have an idea Dmitry?
 [2014-05-05 18:05 UTC] fastest963 at gmail dot com
Instead of (bool) count($array), you can use empty($array), which seems cleaner and more obvious.
Using empty() results in:
$empty      0.10 sec. total
$full       0.10 sec. total
 [2014-08-27 10:01 UTC] nikic@php.net
-Status: Assigned +Status: Closed
 [2014-08-27 10:01 UTC] nikic@php.net
Fixed in PHP 7.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 18 17:01:28 2024 UTC