Недавно читал заметку одного опытного прогера про то, что он давно уже избавился от конструкций типа 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 раза больше времени, чем обработка обычной функции.

П.С. У кого есть возможность запустить тест на PHP 5.x, выложите в комментариях.

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 не сдал позиции.

0   2930

Комментарии ()

  1. Алексей Соин 14 октября 2018 # +1
    Запускал тест на хостинге beget

    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 (анонимная функция)
    1. Сергей Шлоков 14 октября 2018 # 0
      Странное время последней функции. А так всё ровно.
      1. man 30 ноября 2018 # +1
        php 7.1.20 на timeweb
        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 (анонимная функция)
        Последние цифры и правда очень интересные, надоб на выходных исследовать этот момент.

    Вы должны авторизоваться, чтобы оставлять комментарии.

    Выделите опечатку и нажмите Ctrl + Enter, чтобы отправить сообщение об ошибке.