Jaka jest różnica w wydajności (jeśli istnieje) między tymi trzema podejściami, które są używane do przekształcania tablicy w inną tablicę?
- Za pomocą
foreach
- Używanie
array_map
z funkcją lambda / closure - Używanie
array_map
z funkcją / metodą „statyczną” - Czy jest jakieś inne podejście?
Aby się wyjaśnić, spójrzmy na przykłady, wszystkie robią to samo - mnożąc tablicę liczb przez 10:
$numbers = range(0, 1000);
Dla każdego
$result = array();
foreach ($numbers as $number) {
$result[] = $number * 10;
}
return $result;
Mapa z lambdą
return array_map(function($number) {
return $number * 10;
}, $numbers);
Mapa z funkcją „static”, przekazywana jako odniesienie do ciągu
function tenTimes($number) {
return $number * 10;
}
return array_map('tenTimes', $numbers);
Czy jest jakieś inne podejście? Z przyjemnością usłyszę właściwie wszystkie różnice między powyższymi przypadkami i wszelkie uwagi, dlaczego warto zastosować jeden zamiast innych.
Odpowiedzi:
FWIW, właśnie wykonałem test porównawczy, ponieważ plakat tego nie zrobił. Działa na PHP 5.3.10 + XDebug.
UPDATE 2015-01-22 porównaj z odpowiedzią mcfedr poniżej, aby uzyskać dodatkowe wyniki bez XDebug i nowszej wersji PHP.
Otrzymuję dość spójne wyniki z liczbami 1M w kilkunastu próbach:
Zakładając, że słaba prędkość mapy podczas zamykania była spowodowana przez ewaluację zamknięcia za każdym razem, testowałem również w ten sposób:
Ale wyniki są identyczne, co potwierdza, że zamknięcie jest oceniane tylko raz.
UPDATE 02-02 2014: zrzut opcodes
Oto zrzuty kodu operacji dla trzech wywołań zwrotnych. Po pierwsze
useForeach()
:A później
useMapClosure()
i zakończenie, które nazywa:
wtedy
useMapNamed()
funkcja:i nazwana funkcja, którą wywołuje
_tenTimes()
:źródło
useMapNamed
jest to faktycznie szybsze niżuseArray
. Pomyślałem, że warto o tym wspomnieć.lap
, czy nie chcesz, abyrange()
wywołanie było wyższe niż pierwsze połączenie w mikroczasie? (Choć prawdopodobnie nieistotne w porównaniu z czasem na pętlę.)Interesujące jest uruchamianie tego testu przy wyłączonym xdebug, ponieważ xdebug dodaje sporo narzutów, szczególnie do wywołań funkcji.
To jest skrypt FGM uruchamiany przy użyciu 5.6 z xdebug
Bez xdebug
Tutaj jest tylko bardzo niewielka różnica między wersją przednią i zamkniętą.
Ciekawe jest również dodanie wersji z zamknięciem za pomocą
use
Dla porównania dodaję:
Tutaj widzimy, że ma to wpływ na wersję zamknięcia, podczas gdy tablica nie zmieniła się zauważalnie.
19/11/2015 Dodałem teraz również wyniki z wykorzystaniem PHP 7 i HHVM do porównania. Wnioski są podobne, choć wszystko przebiega znacznie szybciej.
źródło
array_map
(i powiązane z nią funkcjearray_reduce
,array_filter
) pozwalają pisać piękną kod. Gdybyarray_map
był znacznie wolniejszy, byłby to powód do użyciaforeach
, ale jest bardzo podobny, więc będę używaćarray_map
wszędzie, gdzie ma to sens.To interesujące. Ale mam odwrotny wynik z następującymi kodami, które są uproszczone z moich obecnych projektów:
Oto moje dane i kody testowe:
Wynik to:
Moje testy odbywały się w środowisku produkcyjnym LAMP bez xdebug. Błądzę, xdebug spowolniłby wydajność array_map.
źródło
array_map
;)array_map
iforeach
używam Xhprof. A jego interesującearray_map
pochłania więcej pamięci niż „foreach”.