php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #66325 is_array argument is not passed by reference
Submitted: 2013-12-19 18:01 UTC Modified: 2013-12-20 03:22 UTC
From: ujvari at microsec dot hu Assigned:
Status: Not a bug Package: Arrays related
PHP Version: Irrelevant OS:
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: ujvari at microsec dot hu
New email:
PHP Version: OS:

 

 [2013-12-19 18:01 UTC] ujvari at microsec dot hu
Description:
------------
The is_array() function does not takes it's argument by reference, but copies it. When it takes a large array as an argument and it is called this way many times (for example in a "for" cycle) then it can take a huge time to run beacause of large amount of memory copies.

The same problem probably exists at other array related functions.

In PHP 5.3 and earlier you cound use is_array(&$array) to mitigate the performance bottleneck. Since call-time pass-by-reference was removed in PHP 5.4 there is no way to do a workaround anymore.

Test script:
---------------
<?php

function delta($prefix, $t1) {
        $t2 = microtime(true);
        printf("%s %0.6f\n", $prefix, ($t2 - $t1) * 1000);
}

function &genarray() {
        $a = array();
        for($i = 0; $i < 10000; $i++) {
                $a[] = $i;
        }
        return($a);
}

function noref(&$a) {
        for($i = 0; $i < 10000; $i++) {
                is_array($a);
        }
}

function byref(&$a) {
        for($i = 0; $i < 10000; $i++) {
                is_array(&$a);
        }
}

$a = &genarray();
$t1 = microtime(true);
noref($a);
delta("NoRef:", $t1);

$t3 = microtime(true);
byref($a);
delta("ByRef:", $t3);

?>


Expected result:
----------------
I expected that NoRef timing be (almost) equal to ByRef timing.

Actual result:
--------------
NoRef: 9246.673107
ByRef: 1.910925

NoRef is ~5000 times slower than ByRef.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-12-19 19:19 UTC] anon at anon dot anon
PHP variables are copy-on-write. They use low-level references everywhere internally. However, a value cannot be referred to both byval and byref at the same time, so using references actually makes it more likely that the value will need to be copied, which is what's happening in your code. If you simply REMOVE every ampersand from your sample program, you will see the same high performance from both functions.

Related: http://www.php.net/manual/en/features.gc.refcounting-basics.php.
 [2013-12-20 03:22 UTC] laruence@php.net
-Status: Open +Status: Not a bug
 [2013-12-20 03:22 UTC] laruence@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php


 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Tue Sep 21 03:03:36 2021 UTC