Циклы в PHP
Недавно читал заметку одного опытного прогера про то, что он давно уже избавился от конструкций типа if
, foreach
, заменив первый на тернарный оператор, а последний на array_map/array_walk
. Плюс ещё какие-то приёмы. Ну прочитал и забыл. А сейчас решил освежить память и никак не могу вспомнить, где читал. То ли на медиуме, то ли на freeCodeCamp'е. Но не суть. Озадачился я вопросом быстродействия этих решений.
Сравнивать if
с тернарным оператором особо не имеет смысла, а вот приём с array_map
решил проверить. Написал простенький тест. Результат получился неожиданным — foreach
быстрее array_map
. Картина маслом. Проверял я на PHP 7. На пятёрке не вижу смысла это делать.
Ради интереса решил протестировать основные конструкции цикла. Причем варианты array_map
и array_walk
вызываются в двух вариантах — с анонимной фукнцией и обычной (объявленной). Для большей наглядности я взял массив из миллиона элементов.
<?php $numbers = 1000000; $items = range(0, $numbers); #1 Foreach $tstart= microtime(true); $result = []; foreach ($items as $item) { $result[] = $item * 10; } echo number_format(microtime(true) - $tstart, 10), ": foreach", "<br>"; #2 For $tstart= microtime(true); $result = []; for ($i=0; $i<=$numbers; $i++) { $result[] = $items[$i] * 10; } echo number_format(microtime(true) - $tstart, 10), ": for" ,"<br>"; #3 While $tstart= microtime(true); $result = []; while ($numbers >= 0) { $result[] = $items[$numbers] * 10; $numbers--; } echo number_format(microtime(true) - $tstart, 10), ": while" ,"<br>"; #4 array_map (usual function) $tstart= microtime(true); function multi10($number) { return $number * 10; } $result = array_map('multi10', $items); echo number_format(microtime(true) - $tstart, 10), ": array_map (обычная функция)", "<br>"; #5 array_map (lambda function) $tstart= microtime(true); $result = array_map(function($number) { return $number * 10; }, $items); echo number_format(microtime(true) - $tstart, 10), ": array_map (анонимная функция)", "<br>"; #6 array_walk (usual function) $tstart= microtime(true); $result = array_walk($items, 'multi10'); echo number_format(microtime(true) - $tstart, 10), ": array_walk (обычная функция)", "<br>"; #7 array_walk (lambda function) $items = range(0, $numbers); $tstart= microtime(true); $result = array_walk($items, function($number) { return $number * 10; }); echo number_format(microtime(true) - $tstart, 10), ": array_walk (анонимная функция)", "<br>";
И вот какой результат:
0.2690150738: foreach 0.3570210934: for 0.3400189877: while 0.8420479298: array_map (обычная функция) 1.8021039963: array_map (анонимная функция) 0.8600490093: array_walk (обычная функция) 1.8251039982: array_walk (анонимная функция)
В общем, вывод напрашивается сам собой — доверяй, но проверяй. foreach
оказался самым быстрым и отказываться от него было бы глупо. Хотя в своё время читал, что for
самый пресамый.
Лично моё мнение, использовать array_map
нужно только при оправданной необходимости. Кстати, обратите внимание на то, что обработка анонимной функции отнимает в 2 раза больше времени, чем обработка обычной функции.
Update 22.08.2018
Запустил данный скрипт на modhost.pro. Всё-таки окружение на локалке отличается от реального на сайте. Количество итераций снижено до 1000 из-за ограничений памяти на тестовом сайте.
0.0000169277: foreach 0.0000212193: for 0.0000209808: while 0.0000278950: array_map (обычная функция) 0.0000321865: array_map (анонимная функция) 0.0000429153: array_walk (обычная функция) 0.0000419617: array_walk (анонимная функция)
Как видите, разница получилась не такая уж и большая, но всё равно foreach
не сдал позиции.
Комментарии ()
Вы должны авторизоваться, чтобы оставлять комментарии.
PHP7.0
0.0728318691: foreach
0.0921568871: for
0.0918550491: while
0.0943019390: array_map (обычная функция)
0.0788431168: array_map (анонимная функция)
0.1036560535: array_walk (обычная функция)
0.0000200272: array_walk (анонимная функция)
PHP5.6
0.0749831200: foreach
0.0928089619: for
0.0897529125: while
0.0786218643: array_map (обычная функция)
0.0798480511: array_map (анонимная функция)
0.1028718948: array_walk (обычная функция)
0.0000100136: array_walk (анонимная функция)
PHP5.3
0.0742721558: foreach
0.0898149014: for
0.0897319317: while
0.0826630592: array_map (обычная функция)
0.0833039284: array_map (анонимная функция)
0.1059038639: array_walk (обычная функция)
0.0000181198: array_walk (анонимная функция)
0.0357680321: foreach
0.0446281433: for
0.0449008942: while
0.0569660664: array_map (обычная функция)
0.0582380295: array_map (анонимная функция)
0.0795629025: array_walk (обычная функция)
0.0000078678: array_walk (анонимная функция)
Последние цифры и правда очень интересные, надоб на выходных исследовать этот момент.