php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #71153 Performance Degradation in ArrayIterator with large arrays
Submitted: 2015-12-17 19:28 UTC Modified: 2015-12-17 19:47 UTC
Votes:1
Avg. Score:3.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:0 (0.0%)
From: kontakt at beberlei dot de Assigned: nikic (profile)
Status: Closed Package: *General Issues
PHP Version: 7.0.1 OS: Linux/Ubuntu 15.04
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 you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: kontakt at beberlei dot de
New email:
PHP Version: OS:

 

 [2015-12-17 19:28 UTC] kontakt at beberlei dot de
Description:
------------
When creating array iterators with large array, iterating over them will be *much* slower than just iterating over the array itself. The larger the array gets the exponentially slower the iteration gets. Memory usage increases as well.

For the same script PHP 5 doesn't have the problem, it is pretty fast on any size of array iterator.

This problem was found in Twig, see my explanation comment: https://github.com/twigphp/Twig/issues/1810



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

class Node implements IteratorAggregate
{
    private $nodes;

    public function __construct(array $nodes)
    {
        $this->nodes = $nodes;
    }

    public function getIterator()
    {
        return new ArrayIterator($this->nodes);
    }

    public function getNodes()
    {
        return $this->nodes;
    }

    public function visitIterator()
    {
        foreach ($this as $node) {
            $node->visitIterator();
        }
    }

    public function visitNodes()
    {
        foreach ($this->getNodes() as $node) {
            $node->visitNodes();
        }
    }
}

gc_disable();

$sizes = [1000, 10000, 20000, 65000, 66000, 100000];

foreach ($sizes as $size) {
    echo "Array Size $size\n";
    $nodes = [];
    for ($i = 0; $i < $size; $i++) {
        $nodes[] = new Node([]);
    }
    $node = new Node($nodes);

    $time = microtime(true);
    $node->visitNodes();
    echo "Array: " . number_format(microtime(true) - $time , 4) . " " . memory_get_peak_usage() . "\n";

    $time = microtime(true);
    $node->visitIterator();
    echo "Iterator: " . number_format(microtime(true) - $time , 4) . " " . memory_get_peak_usage() . "\n";
    echo "\n";
}

Expected result:
----------------
PHP 7 being faster than PHP 5 on every size of ArrayIterator, not just with size 1000.

Actual result:
--------------
Array Size 1000
Array: 0.0001 695232
Iterator: 0.0009 730208

Array Size 10000
Array: 0.0019 2464128
Iterator: 0.0607 3003872

Array Size 20000
Array: 0.0027 5898752
Iterator: 0.5189 5898752

Array Size 65000
Array: 0.0130 14741656
Iterator: 5.0322 14741656

Array Size 66000
Array: 0.0107 24079792
Iterator: 12.1315 24079792

Array Size 100000
Array: 0.0141 32198240
Iterator: 34.8082 32198240


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-12-17 19:47 UTC] nikic@php.net
-Assigned To: +Assigned To: nikic
 [2015-12-17 19:49 UTC] kontakt at beberlei dot de
Ok it problem seems iteration over an empty ArrayIterator,

removing the recursive call $node->visitIterator(); inside the method makes php7 implementation faster than the php5 one.
 [2015-12-17 20:03 UTC] nikic@php.net
Automatic comment on behalf of nikic
Revision: http://git.php.net/?p=php-src.git;a=commit;h=a3e19527004dc67dfd875e758007b8ae135d4ed1
Log: Fixed bug #71153
 [2015-12-17 20:03 UTC] nikic@php.net
-Status: Assigned +Status: Closed
 [2016-07-20 11:34 UTC] davey@php.net
Automatic comment on behalf of nikic
Revision: http://git.php.net/?p=php-src.git;a=commit;h=a3e19527004dc67dfd875e758007b8ae135d4ed1
Log: Fixed bug #71153
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Oct 27 16:01:27 2024 UTC