Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

PHP vs Zephir performence part 2

I made some easy benchmark for merging two multi demands arrays with KEY value sum:

  public static function arrayMergeWithSum2d($b, $a){

        $keys = array_keys($a);

        foreach($keys as $key_a){
            foreach($a[$key_a] as $key_aa => $value_aa){
                if(isset($b[$key_a][$key_aa])){
                    $b[$key_a][$key_aa] += $value_aa;
                }elseif(isset($b[$key_a])){
                    $b[$key_a][$key_aa] = $value_aa;
                }else{
                    $b[$key_a] = [];
                    $b[$key_a][$key_aa] = $value_aa;
                }
            }
        }
        return $b;
    }
    public static function arrayMergeWithSum2d(array a1, array a2)
    {
        var _key;
        var keys;
        let keys = array_keys(a2);

        for _key in keys {
            var __key;
            var __value;            
            for __key, __value in a2[_key] {

            if(isset(a1[_key][__key])){
                    let a1[_key][__key] = a1[_key][__key] + __value;
                }elseif(isset(a1[_key])){
                    let a1[_key][__key] = __value;
                }else{
                    let a1[_key] = [];
                    let a1[_key][__key] = __value;
                }
            }
        }
        return a1;
    }

Results:


for array A[10x10] with B[10x10]

PHP: 7.8916549682617E-5sek

ZEPHIR: 0.00012397766113281sek


for array A[100x100] with B[100x100]

PHP: 0.0046660900115967sek

ZEPHIR: 0.058029890060425sek


for array A[1000x1000] with B[10x10]

PHP: 0.0013449192047119sek

ZEPHIR: 33.563272953033sek


PHP 5.4.38-0+deb7u1 (cli) (built: Feb 25 2015 09:55:35) zephir version 0.7.0b


PHP is much faster than Zephir... Why?



634
Accepted
answer

To find out what is going on here, I modified your functions and get Zipher more than 3 times faster than PHP.

Conclusion

To keep loops with array modifications fast, you shouldn't use redundant references to arrays like you did with: a1[key][key]. Instead you can resolve let c=a1[key] and work with it in the loop like: c[key] = ... After the loop you copy the ready c to a1[key]: let a1[key] = c PHP behaves the same, but it has not the same extrem effect on performance.

Benchmark Results

Zephir - Fast Method : 0.054473876953125 
Zephir - Slow Method : 6.6276879310608 
PHP -- Fast Function : 0.1818630695343 
PHP -- Slow Function : 0.23329997062683

Code

namespace Utils;

class ArrayUtils
{

    public static function arrayMergeSum2D_FastWay(array a, array b)
    {
        var _key;
        var __key;
        var __value;  
        var c;

        for _key, _ in b 
        {
            if !isset a[_key] { let a[_key] = []; }
            let c = a[_key]; // copy array

            for __key, __value in b[_key] 
            {

                if !isset c[__key]  { let c[__key] = 0; }
                let c[__key] = c[__key] + __value;
            }

            let a[_key] = c; // copy array
        }

        return a;
    }

    public static function arrayMergeSum2D_SlowWay(array a, array b)
    {
        var _key;
        var __key;
        var __value;  

        for _key, _ in b 
        {
            if !isset a[_key] { let a[_key] = []; }

            for __key, __value in b[_key] 
            {
                if !isset a[_key][__key] { let a[_key][__key] = 0; }
                let a[_key][__key] = a[_key][__key] + __value;
            }
        }

        return a;
    }

}
<?php

function createArray($count1, $count2, $skipRandom)
{
    $a = array();

    for ($i = 0; $i < $count1; $i++) 
    {
        $c = array();

        for ($k = 0; $k < $count2; $k++) 
        {
            if( !$skipRandom || $k % 2 == 1 ) $c[$k] = $skipRandom ? 11 : 100;
        }

        if( !$skipRandom || $i % 2 == 1 ) $a[$i] = $c;
    }

    return $a;
}

function arrayMergeSum2D_Fast($a, $b)
{
    foreach( $b as $_key => $_value )
    {
        if( !isset( $a[$_key] ) ) $a[$_key] = []; 
        $c = $a[$_key]; // copy array

        foreach( $b[$_key] as $__key => $__value )
        {

            if( !isset( $c[$__key]  ) ) $c[$__key] = 0; 

            $c[$__key] +=  $__value;
        }

        $a[$_key] = $c; // copy array
    }
    return $a;
}

function arrayMergeSum2D_Slow($a, $b)
{
    foreach( $b as $_key => $_value )
    {
        if( !isset( $a[$_key] ) ) $a[$_key] = []; 

        foreach( $b[$_key] as $__key => $__value )
        {
            if( !isset( $a[$_key][$__key]   ) ) $a[$_key][$__key] = 0; 

            $a[$_key][$__key] += $__value;
        }
    }
    return $a;
}




$count = 500; // max:500 / set the length of arrays (subarrays) / count=20 => 20 x 20 = 400 entries

$a = createArray($count,$count,true);  // create incomplete array with values of 11 
//var_dump($a);
$b = createArray($count,$count,false); // create complete array with values of 100
//var_dump($b);




echo "<br> Benchmark Calculation Methods <br><code>";

$t = microtime(true);
$c = Utils\ArrayUtils::arrayMergeSum2D_FastWay($a,$b);
echo "<br>Zephir - Fast Method : ",microtime(true) - $t, PHP_EOL;
 // ksort($c); var_dump($c);

$t = microtime(true);
$c = Utils\ArrayUtils::arrayMergeSum2D_SlowWay($a,$b);
echo "<br>Zephir - Slow Method : ",microtime(true) - $t, PHP_EOL;
 // ksort($c); var_dump($c);

$t = microtime(true);
$c = arrayMergeSum2D_Fast($a,$b);
echo "<br>PHP -- Fast Function : ",microtime(true) - $t, PHP_EOL;
// ksort($c); var_dump($c);

$t = microtime(true);
$c = arrayMergeSum2D_Slow($a,$b);
echo "<br>PHP -- Slow Function : ",microtime(true) - $t, PHP_EOL;
// ksort($c); var_dump($c);

echo "</code>";