Loops are where time goes when data is large. Most loop speed-ups come from doing less work per item and avoiding loops inside loops.
1. Avoid nested loops over big data
A loop inside a loop does n x m steps. For 1,000 x 1,000 items, that is a million.
<?php
$a = range(1, 2000);
$b = range(1000, 3000);
// Nested: up to 2000 * 2001 comparisons
$common = [];
foreach ($a as $x) {
foreach ($b as $y) {
if ($x === $y) {
$common[] = $x;
break;
}
}
}
// Lookup: about 2000 + 2001 steps
$lookup = array_flip($b);
$common2 = [];
foreach ($a as $x) {
if (isset($lookup[$x])) {
$common2[] = $x;
}
}
echo count($common) . " " . count($common2) . " " . (($common === $common2) ? "same" : "different");
1001 1001 same
Turning one list into an array keyed by the values (array_flip(), array_column()) makes the inner check instant.
2. Use built-in array functions
Functions such as array_sum(), array_filter(), in_array(), array_unique(), array_column() and sort() run in fast C code. They are usually faster and clearer than a hand-written loop.
<?php
$prices = [120, 45, 300, 80];
$total = array_sum($prices);
$expensive = array_filter($prices, fn($p) => $p > 100);
echo $total . " " . count($expensive);
545 2
3. Stop early
If you only need the first match, leave the loop as soon as you find it.
<?php
function firstNegative(array $numbers): ?int
{
foreach ($numbers as $n) {
if ($n < 0) {
return $n; // stop here, do not scan the rest
}
}
return null;
}
var_dump(firstNegative([4, 8, -3, 9, -1]));
int(-3)
4. Do cheap checks first
Order conditions so the cheap and most selective check comes first. && stops at the first false.
<?php
if ($user->isActive() && expensiveCheck($user)) { // the expensive call runs only for active users
// ...
}
5. Build strings with implode, not endless concatenation in loops
For small loops it does not matter. For very large output, collect pieces in an array and implode() once.
<?php
$parts = [];
foreach (range(1, 5) as $i) {
$parts[] = "<li>$i</li>";
}
echo implode("", $parts);
<li>1</li><li>2</li><li>3</li><li>4</li><li>5</li>
6. Use generators for large sequences
A generator avoids building the whole list first (see Generators).
7. Do not run queries or API calls in loops
This is the biggest loop mistake. See Avoiding Repeated Work.
8. Choose the right data structure
| Need | Use |
|---|---|
| Fast “is this value in the set?” | An array with values as keys (isset($set[$v])) |
| A queue or stack | SplQueue, SplStack, or array_push/array_pop |
| Sorted data you insert into | SplMinHeap, SplPriorityQueue |
| Fixed-size numeric arrays | SplFixedArray (saves memory) |
9. Do not micro-optimise
These make no meaningful difference in real code:
forvsforeachvswhile.++$ivs$i++.- Single vs double quotes.
count()in the loop condition (PHP optimises it for arrays).
Readability matters more. Optimise algorithms and I/O, not syntax.
10. Measure
If a loop is slow, time it and profile it (see Measuring Performance). Often the real cost is something inside the loop, such as a function call that reads a file.
O(n) vs O(n squared)
n x n algorithm gets slow much faster than an n one. Ask: “what happens if there are 100 times more items?” before you finish a loop.