array_map vs loop and operation
Asked Answered
F

2

37

Using:

for($i=1; $i<= 10000; ++$i) {
    $arrayOfNumbers[] = rand(1, 99999);
}

Can some explain why there is such a speed difference:

array_map(array($maxHeap, 'insert'), $arrayOfNumbers);
# Avg Time: 0.92856907844543s

# against

foreach($arrayOfNumbers as $number) {
    $maxHeap->insert($number);
}
# Avg Time: 1.3148670101166

$maxHeap being an object class MaxHeap extends SplMaxHeap

Felicafelicdad answered 6/12, 2011 at 5:50 Comment(4)
If you are going to downvote please give a reason!Felicafelicdad
Interesting question, as far as I was aware PHP's array_map() was internally represented as a foreach - correct me if I'm wrong please.Putup
because every function/method that is built-in have less opcode calling overhead than doing it manually. array_map is built-in method which handles the array in C level rather than opcode and then in C. P.S. as I see your $arrayOfNumbers loop.. I have to tell you this too: foreach is faster than while, while is faster than for. If you use it for iterating an array, use foreach. For is the slowest because it does 2 checks every iteration. First to check ending condition and secondly it's doing that ++$i. So try to use foreach(range(1,1000) as $i) instead of that for and benchmark that.Derryberry
p.p.s. Also, method call in that second foreach is another do-something-via-opcode overhead. Objects are slower than functions in nearly every language, including php. So in fact you are generating this (think in opcode): [what is $arrayOfNumbers? lookup] loop:[get next array item in foreach][assign variable $number][$maxHeap? oh, I have to lookup that][is it object? can i call insert on it? raise exception if not][I'm calling it, with argument][put that argument to COW buffer][continue doing something else in insert][check for return value][nothing? good.][next loop if we can].Derryberry
C
2

It is due to the difference between Callback functions and normal functions.

In the second one, iteration of array using foreach, each iteration calls "insert" function and wait for the execution (function return control) and proceed to next iteration.

But in the array_map function, "insert" happens as callback function, it calls "insert" and don't wait for the result and call insert with next item in the array. So it is faster.

Hope it helps.

Couvade answered 16/12, 2011 at 15:50 Comment(2)
I wonder how that can be true: array_map returns an array of what the callback returned... That's the behavior of "map".Stammel
I also strongly doubt that php runs the calls asynchronously. -1 due to the lack of a good reference.Tedmann
G
14

To my knowledge php doesn't do anything asynchronously, in contrast to Sajith Amma's answer.

I suspect that this is actually due to differences in the lookup of $maxHeap->insert.

With the foreach loop the you are calling $maxHeap->insert within the current scope, the php interpreter has to look up maxHeap then lookup insert on the maxHeap instance. Within the scope of the script you are running there might be other variables which can make the lookup slower.

With the array_map the php interpreter knows it will be calling the exact same $maxHeap->insert, it can do the lookup just once and use the same 'code address' for the rest of the iterations.

Gigigigli answered 9/4, 2013 at 8:34 Comment(0)
C
2

It is due to the difference between Callback functions and normal functions.

In the second one, iteration of array using foreach, each iteration calls "insert" function and wait for the execution (function return control) and proceed to next iteration.

But in the array_map function, "insert" happens as callback function, it calls "insert" and don't wait for the result and call insert with next item in the array. So it is faster.

Hope it helps.

Couvade answered 16/12, 2011 at 15:50 Comment(2)
I wonder how that can be true: array_map returns an array of what the callback returned... That's the behavior of "map".Stammel
I also strongly doubt that php runs the calls asynchronously. -1 due to the lack of a good reference.Tedmann

© 2022 - 2024 — McMap. All rights reserved.