4

I stumbled upon the question "Find the last element of an array while using a foreach loop in PHP" here at SO.

In the comments user "johndodo" was claiming that there is no performance penalty for accessing count($array) each time in a foreach loop.

"[...] in PHP there is no performance penalty for accessing count($arr) each time. The reason is that items count is internally saved as special field in the array header and is not calculated on-the-fly. [...]"

So:

foreach ($array as $line) {
    $output .= '    ' . $line;
    // add LF if not the last line
    if ($array[count($array) - 1] != $line) {
        $output .= "\n";
    }
}

Should be equally as fast as:

$arrayLen = count($array) - 1;
foreach ($array as $line) {
    $output .= '    ' . $line;
    // add LF if not the last line
    if ($array[$arrayLen] != $line) {
        $output .= "\n";
    }
}

Well this is not the case. When doing profiling one can tell that a considerable amount of time is spent on doing count() in the first example. Is it because the claim laid forward by the user is moot or is it because we are calling a function in our tight foreach loop?

Community
  • 1
  • 1
user555
  • 1,564
  • 2
  • 15
  • 29
  • 2
    Cause you're calling a function for each iteration of the loop. This is a particularly common mistake when creating for loops: ie for( $i = 0; $i < count($some_amount); $i ++). You're best off calling count() as few times as possible, even if it means creating another variable to hold the result. – Shawn Wernig Jan 25 '14 at 21:42
  • 1
    Yep assuming a large dataset, the second version with `$arrayLen = count();` is a much better. And a good practice to keep in general. – The Thirsty Ape Jan 25 '14 at 21:47
  • Is it because function calls are expensive or that `count()` recounts the array on each iteration? – user555 Jan 25 '14 at 21:52
  • 1
    It's an overhead for a function call: but the array structure includes a count value internally, so it doesn't need to loop over the array counting each element every time... even so, the performance difference is noticeable with larger arrays – Mark Baker Jan 25 '14 at 21:56
  • I would use `array_map` and `join`, for readability. not sure if it's faster though... does it even matter? – Karoly Horvath Jan 25 '14 at 21:58
  • @KarolyHorvath I would rather do `$output = substr($output, 0, -1);` after the foreach and get rid of the counting entirely. – user555 Jan 25 '14 at 22:04
  • @user555: the `join` gets rid of counting. and still the most readable form. to me. – Karoly Horvath Jan 25 '14 at 22:12
  • 1
    You could possibly test using implode() rather than the loop, though watch for the memory overheads – Mark Baker Jan 25 '14 at 22:21
  • One good way to find out would be to put that loop into another one (let's say 10,000 iterations) and see how much longer it takes.... – nkkollaw Jan 25 '14 at 21:52

1 Answers1

2

What "johndodo" was grasping at is that, as Mark Baker nicely pointed out in the comments, the array structure includes a count value internally, so it doesn't need to loop over the array counting each element every time.

What the statement by "johndodo" failed to consider is that calling a function has a large amount of overhead when called in a loop.

user555
  • 1,564
  • 2
  • 15
  • 29
  • 1
    this quote is ridiculously outdated, nobody uses those architectures anymore. And in PHP pretty much everything is expensive, even reading a variable (yes, obviosuly a function call is more expensive...) – Karoly Horvath Jan 25 '14 at 22:28
  • Why the downvote? @Karoly My point with the quote was that functions calls are expensive no matter the architecture or language. They are so expensive that calling trivial functions in loops should at all cost be avoided. In C/C++ we have the `inline` keyword so that we can do inline expansion, however there is no such functionality in PHP so we have no choice than to manually line those trivial functions, sacrificing code cleanness and duplicating our source code. Anyhow maybe I should just edit out the quote (unless the downvoter things the rest of the answer is also not useful)? – user555 Jan 26 '14 at 21:30
  • Modern compilers will inline small function calls if it makes sense. So that quote is not relevant today. note: http://stackoverflow.com/questions/5971736/c-inline-function – Karoly Horvath Jan 26 '14 at 23:18
  • @KarolyHorvath Yes, but PHP (or rather it's interpreter) doesn't support inline expansion so the quote has at least some merit in the context of PHP. – user555 Jan 27 '14 at 07:12