Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Performance Improvement: Alternative for array_flip function

Is there any way I can avoid using array_flip to optimize performance. I am doing a select statement from database, preparing the query and executing it and storing data as an associative array in $resultCollection and than I have array op and for each element in $resultCollection am storing its outputId in op[] as evident from the code.

I have explained code and so my question is how can I achieve an similar alternative for array_flip with using array_flip as I want to improve performance.

$resultCollection = $statement->fetchAll(PDO::FETCH_ASSOC);

$op = array();

//Looping through result collection and storing unicaOfferId into op array. 
foreach ($resultCollection as $output)
{
$op[] = $output['outputId'];
}

//Here op array has key as 0, 1, 2...and value as id {which I am interested in}

//Flip op array to get offer ids as key

$op = array_flip($op);

//Doing a flip to get id as key. 

foreach ($ft as $Id => $Off)
{
    $ft[$Id]['is_set'] = isset($op[$Id]);
}
like image 220
Rachel Avatar asked Mar 07 '26 23:03

Rachel


1 Answers

I'm adding this answer because you mentioned in the title "Performance Improvement".

TL;DR

You should continue with array_flip(). In the terms of performance compared to a foreach loop, it does things much faster, especially on large arrays (maybe because of its native nature).

Let's test

The result of what I tested (PHP 8.1.5):

Testing an array with 10 elements:
  Average time for array_flip(): 2.0E-5
  Average time for foreach: 3.0E-5
  How much array_flip() is faster: 78%

Testing an array with 100 elements:
  Average time for array_flip(): 0.00011
  Average time for foreach: 0.00025
  How much array_flip() is faster: 137%

Testing an array with 1000 elements:
  Average time for array_flip(): 0.00108
  Average time for foreach: 0.00272
  How much array_flip() is faster: 150%

Testing an array with 10000 elements:
  Average time for array_flip(): 0.00918
  Average time for foreach: 0.02429
  How much array_flip() is faster: 164%

Testing an array with 100000 elements:
  Average time for array_flip(): 0.10644
  Average time for foreach: 0.2439
  How much array_flip() is faster: 129%

Testing an array with 1000000 elements:
  Average time for array_flip(): 0.93669
  Average time for foreach: 2.47616
  How much array_flip() is faster: 164%

Did you see that? Approximately, array_flip() is 2.5 times faster. In addition, it seems the performance of array_flip() increases slightly when the array becomes bigger. So, forget foreach. Even with the help of JIT? Read on...

Could JIT help things out?

Yes! Let's see (PHP 8.1.5, with tracing JIT, opcache.jit_buffer_size = 100M):

Testing an array with 10 elements:
  Average time for array_flip(): 3.0E-5
  Average time for foreach: 3.0E-5
  How much array_flip() is faster: -3%

Testing an array with 100 elements:
  Average time for array_flip(): 0.00011
  Average time for foreach: 0.00011
  How much array_flip() is faster: 0%

Testing an array with 1000 elements:
  Average time for array_flip(): 0.00098
  Average time for foreach: 0.00101
  How much array_flip() is faster: 3%

Testing an array with 10000 elements:
  Average time for array_flip(): 0.00955
  Average time for foreach: 0.00985
  How much array_flip() is faster: 3%

Testing an array with 100000 elements:
  Average time for array_flip(): 0.09958
  Average time for foreach: 0.10182
  How much array_flip() is faster: 2%

Testing an array with 1000000 elements:
  Average time for array_flip(): 0.90585
  Average time for foreach: 1.03467
  How much array_flip() is faster: 14%

Interesting! Notice that:

  • It may seem obvious for some, but tracing JIT starts becoming more useful when you start calling a particular function in a run more and more (try playing with the $iterationsCount in the code below). Also, in most cases you could ignore the performance of a single function call.

  • JIT made everything faster. For array_flip(), it was up to 5-10% performance increase. For foreach, it was magical: about 150% (i.e. 2.5 times faster)!

  • As a result of the previous note, the difference between these two methods reduced drastically. JIT is great and is improving!

Although having a JIT-enabled environment is great, internal functions mostly are faster, independent from your configurations. So, use array_flip().

Talk is cheap...

This is what I tested (feel free to configure variables yourself):

// The ratio of array size being increased
$arraySizeBase = 10;
// Limits of the exponention of the array size
$arraySizePowerMin = 1;
$arraySizePowerMax = 6;

// Number of tests being run within one time capture
$iterationsCount = 100;
// Number of time capture repeats
$repeatCount = 20;
// Precision of rounded result
$precision = 5;

// Array values limits
$minVal = 0;
$maxVal = 10000;

function printTime(callable $x, string $title)
{
    global $iterationsCount, $repeatCount, $precision;

    $tests = [];
    for ($i = 0; $i < $repeatCount; $i++) {
        $startTime = microtime(true);

        for ($j = 0; $j < $iterationsCount; $j++) {
            $x();
        }

        $tests[] = microtime(true) - $startTime;
    }

    $averageTime = array_sum($tests) / $repeatCount;
    echo "  Average time for $title: ", round($averageTime, $precision), PHP_EOL;

    // To be used to calculate ratio
    return $averageTime;
}

$arraySizeMin = $arraySizeBase ** $arraySizePowerMin;
$arraySizeMax = $arraySizeBase ** $arraySizePowerMax;

for ($i = $arraySizeMin; $i <= $arraySizeMax; $i *= $arraySizeBase) {
    // Filling the array with some random stuff
    echo "Testing an array with $i elements:", PHP_EOL;
    $array = array_fill(0, $i - 1, random_int($minVal, $maxVal));

    $arrayFlipTime = printTime(function () use ($array) {
        $flippedArray = array_flip($array);

        // Don't be crazy, clean RAM
        $flippedArray = null;
    }, "array_flip()");

    $foreachTime = printTime(function () use ($array) {
        $flippedArray = [];
        foreach ($array as $key => $value) {
            $flippedArray[$value] = $key;
        }

        // Don't be crazy, clean RAM
        $flippedArray = null;
    }, "foreach");

    // Print a ratio in percentage
    echo "  How much array_flip() is faster: ",
        floor(($foreachTime / $arrayFlipTime) * 100) - 100, "%",
        PHP_EOL;

    echo PHP_EOL;
}
like image 142
MAChitgarha Avatar answered Mar 09 '26 13:03

MAChitgarha



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!