SlowArrayOperationsInLoop
error on by default quick-fixGroup: Performance · PhpStorm name: SlowArrayOperationsInLoopInspection
Two loop anti-patterns:
- Accumulating merges:
$acc = array_merge($acc, $chunk)inside a loop copies the whole accumulator on every iteration (quadratic cost). Collect the chunks and merge once after the loop. - Length in a
forcondition:$i < count($items)re-evaluates the length on every iteration. Compute it once in the initialiser.
Example
php
<?php
function collect(array $batches, $repo)
{
$all = [];
$map = [];
foreach ($batches as $batch) {
$all = array_merge($all, $batch);
$map = \array_replace($batch, $map);
try {
$repo->rows = array_merge_recursive($repo->rows, $batch);
} finally {
}
}
while ($batch = array_shift($batches)) {
$map[$batch['id']] = array_merge($map[$batch['id']], $batch);
if ($batch) {
$all = array_merge($all, $batch);
}
$other = array_merge($all, $batch);
}
foreach ($batches as $batch) {
$all = array_merge($all, $batch);
break;
}
$all = array_merge($all, $map);
for ($n = 0; $n < count($batches); $n++) {}
for ($n = 0, $m = 1; strlen($repo->name) >= $n; $n++) {}
for ($repo->at = 0; $repo->at <= mb_strlen($repo->name); $repo->at++) {}
for (; count($batches) > $n; $n++) {}
for ($n = 0, $total = count($batches); $n < $total; $n++) {}
for ($n = 0; $n < count($batches) - 1; $n++) {}
for ($n = 0; ; $n++) {}
return [$all, $map];
}php
<?php
function collect(array $batches, $repo)
{
$all = [];
$map = [];
foreach ($batches as $batch) {
$all = array_merge($all, $batch);
$map = \array_replace($batch, $map);
try {
$repo->rows = array_merge_recursive($repo->rows, $batch);
} finally {
}
}
while ($batch = array_shift($batches)) {
$map[$batch['id']] = array_merge($map[$batch['id']], $batch);
if ($batch) {
$all = array_merge($all, $batch);
}
$other = array_merge($all, $batch);
}
foreach ($batches as $batch) {
$all = array_merge($all, $batch);
break;
}
$all = array_merge($all, $map);
for ($n = 0, $nMax = count($batches); $n < $nMax; $n++) {}
for ($n = 0, $m = 1, $nMax = strlen($repo->name); $nMax >= $n; $n++) {}
for ($repo->at = 0, $loopsMax = mb_strlen($repo->name); $repo->at <= $loopsMax; $repo->at++) {}
for ($nMax = count($batches); $nMax > $n; $n++) {}
for ($n = 0, $total = count($batches); $n < $total; $n++) {}
for ($n = 0; $n < count($batches) - 1; $n++) {}
for ($n = 0; ; $n++) {}
return [$all, $map];
}Reported:
- line 7: 'array_merge(...)' inside a loop re-copies the accumulator each time; merge once after the loop.
- line 8: 'array_replace(...)' inside a loop re-copies the accumulator each time; merge once after the loop.
- line 10: 'array_merge_recursive(...)' inside a loop re-copies the accumulator each time; merge once after the loop.
- line 27: 'count(...)' is re-evaluated on every iteration; compute it once before the loop.
- line 28: 'strlen(...)' is re-evaluated on every iteration; compute it once before the loop.
- line 29: 'mb_strlen(...)' is re-evaluated on every iteration; compute it once before the loop.
- line 30: 'count(...)' is re-evaluated on every iteration; compute it once before the loop.
Configure
In custos.json:
json
{
"rules": {
"SlowArrayOperationsInLoop": {
"enabled": false
}
}
}Suppress
Before the statement or declaration (or the first statement of the file), either of:
php
// @custos-ignore SlowArrayOperationsInLoop
/**
* @noinspection SlowArrayOperationsInLoopInspection
*/