php - 性能提升 : Alternative for array_flip function

标签 php performance

有什么方法可以避免使用 array_flip 来优化性能。我正在从数据库中执行 select 语句,准备查询并执行它,并将数据作为关联数组存储在 $resultCollection 中,然后我有数组 op 并且对于 $resultCollection 中的每个元素,我将其 outputId 存储在 op[] 中,从代码中可以明显看出。

我已经解释了代码,所以我的问题是如何使用 array_flip 实现 array_flip 的类似替代方案,因为我想提高性能。

$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]);
}

最佳答案

我添加这个答案是因为您在标题“性能改进”中提到过。

长话短说

你应该继续 array_flip() .就性能而言,与 foreach 循环相比,它执行速度更快,尤其是在大型数组上(可能是因为它的 native 特性)。

让我们测试一下

我测试的结果(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%

你看到了吗? array_flip() 大约快 2.5 倍。此外,当数组变大时,array_flip() 的性能似乎略有提高。所以,忘记 foreach。即使有 JIT 的帮助?继续阅读...

JIT 能解决问题吗?

是的!让我们看看(PHP 8.1.5,跟踪 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%

有趣!请注意:

  • 对于某些人来说这似乎是显而易见的,但是当您开始越来越多地在运行中调用特定函数时,跟踪 JIT 开始变得更加有用(尝试在代码中使用 $iterationsCount以下)。此外,在大多数情况下,您可以忽略单个函数调用的性能。

  • JIT 让一切变得更快。对于 array_flip(),性能提升高达 5-10%。对于 foreach,它是神奇的:大约 150%(即快 2.5 倍)!

  • 根据前面的注释,这两种方法之间的差异大大缩小了。 JIT 很棒并且正在改进!

虽然支持 JIT 的环境很棒,但内部函数大多速度更快,并且独立于您的配置。所以,使用 array_flip()

空谈是廉价的...

这是我测试过的(随意配置变量):

// 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;
}

关于php - 性能提升 : Alternative for array_flip function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2473566/

相关文章:

php - 在 WordPress 中修剪 esc_attr() 中的空格?

php - 区分新异常与现有异常

php - 如何显示与特定值匹配的特定数据库行中的数据

javascript - 在 JavaScript 中连接字符串的最有效方法是什么?

performance - Google Cloud Functions CPU 速度设置

php - 自动 uploader

php - CodeIgniter 第三方类未加载

database - (Web) 服务依赖问题

mysql - 时间戳 vs 日期时间 vs int - 有和没有索引 - 测试

mysql - Mysql大表优化