Который имеет лучшую производительность? For или Foreach,+Range?


две формы ниже, который имеет лучшую производительность?

  1. For:

    for( $x=1; $x < 31; $x++ )
       echo $x . PHP_EOL;
    
  2. Foreach + range:

    foreach( range(1,30) as $x )
       echo $x . PHP_EOL;
    

я Знаю, что разница, вероятно, будет в миллисекундах, но это стоит изучения, так как в приложение с большой трафик, эти миллисекунды могут сделать разницу.

, Если существует третий способ еще более высокой производительности, пожалуйста, выберите.

Author: stderr, 2015-05-08

2 answers

for владел производительность немного лучше о foreach, в данном случае, поскольку функции range возвращает array элементов, в результате итерации и проверяет каждый элемент этого.

См. сравнительный две фигуры в loop 350000 итераций:

function bench($func) {
    $tempo = -microtime(true);
    $func();
    $tempo += microtime(true);
    return number_format($tempo, 4);
}

function func1() {
    for($x = 1; $x < 350000; $x++) echo $x;
}

function func2() {
    foreach(range(1, 350000) as $x) echo $x;
}

$tempoDecorrido = bench('func1');
echo "\n For => Tempo decorrido: {$tempoDecorrido} segundos \n";

$tempoDecorrido = bench('func2');
echo "\n Foreach => Tempo decorrido: {$tempoDecorrido} segundos \n";

Результат:

12345678910....
For => Tempo decorrido: 0.48403 segundos
1234567891011....
Foreach => Tempo decorrido: 0.74004 segundos

Результат может быть очень разному в зависимости от среды выполнения. Другие способы измерения производительности кода на PHP можно увидеть на вопрос Как измерить производительность кода на PHP?

Вопрос: До какой степени преждевременная оптимизация-это проблема?

Альтернативных

Начиная с PHP 5.5 была введена поддержка Генераторы, идея, лежащая генераторы в том, что функция не возвращает одно значение, но да последовательность значений, вместо этого, где каждое значение является выдан , к. Другими словами, генераторы позволяют реализовать Итераторы так проще и без сложностей реализации класса, который реализует интерфейс Iterator.

Преимущество использования генераторы является возможность выполнять итерацию по набору данных нет положить их в памяти сразу, то функции range() не делает. Когда функция генератора выполняется, возвращается через зарезервированное слово yield (тип return особое), "ключ/значение" и, при появлении следующего элемента Iterator, функция генератор продолжается, где остановился последний yield.

Ниже приведен другой сравнительный, сейчас в loop 600000 итераций, и, сравнивая функции генератора, xrange:

function bench($func){
    $tempo = -microtime(true);
    echo $func();
    $tempo += microtime(true);
    return number_format($tempo, 4);
}

function xrange($inicio, $fim, $passo = 1) {
    for ($i = $inicio; $i <= $fim; $i += $passo) yield $i;
}
function func1(){
    for($x = 1; $x < 600000; $x++) echo $x;
}
function func2(){
    foreach(xrange(1, 600000) as $x) echo $x;
}
function func3(){
    foreach(range(1, 600000) as $x) echo $x;
}
$tempo = bench('func1');
echo "\n For: {$tempo} \n";
$tempo = bench('func2');
echo "\n xrange: {$tempo} \n";
$tempo = bench('func3');
echo "\n range: {$tempo} \n";

Результат:

1234567891011121314151...
For: 1.0861
123456789101112131415161...
xrange: 2.5801
12345678910111213141516171...
range: 2.7602

Использовать один или другой, мало будет влиять на производительность, используйте foreach в ситуациях, где требуется только подметать array, for, для ситуаций, где необходимо работать с index элементов, например, доступ к элементам более ранних или более поздних версий в текущей итерации. Уже Генераторы, используйте в ситуациях, где требуется устранить ограничения памяти.

 6
Author: stderr, 2017-04-13 12:59:44

Мое личное мнение, использовать то, что имеет смысл в контексте. Разница во времени будет минимальной, в большинстве случаев.

Большая вещь, чтобы отметить:

for( $x=1; $x < 31; $x++ )

Это цикл дорого, учитывая, что он называет число на каждой итерации. Однако если вы не делаете это, я не думаю, что действительно будет иметь значения ...

Что Касается, foreach, во втором случае будет "эквивалентно" a:

$It->rewind();
while ($it->valido()) {
    $key = $it->key(); // Se estiver usando $key => sintaxe $value
    $value = $it->current();

    // conteúdo do loop aqui

    $it->next();
}

Только увидеть, уже поняли, что это сложнее, чем первое.

Есть способы более быстрые, чтобы сделать итерации, и это зависит от проблемы.

Будем имитировать гонку между FOR FOREACH:

$start = microtime(true);
for ($x = 1; $x < 31; $x++) {}
echo "Concluído em", microtime(true) - $start, "Segundos \n"

$start = microtime(true);
for (range(1,30) as $x ) {}
echo "Concluído em", microtime(true) - $start, "Segundos \n"

Результаты могут отличаться в зависимости от среды выполнения.

Другие сравнения:

$a = array();
for ($i = 0; $i < 31; $i++) {
    $a[] = $i;
}

$start = microtime(true);
foreach ($a as $k => $v) {
    $a[$k] = $v + 1;
}
echo "Concluído em", microtime(true) - $start, "Segundos \n";

$start = microtime (true);
foreach (($a as $k => &$v) {
    $v = $v + 1;
}
echo "Concluído em", microtime (true) - $start, "Segundos \n";

$start = microtime (true);
foreach ($a as $k => $v) {}
echo "Concluído em", microtime (true) - $start, "Segundos \n";

$start = microtime (true);
foreach ($a as $k => &$v) {}
echo "Concluído em", microtime (true) - $start, "Segundos \n";

:

Concluído em:  0.00161790847778  Segundos 
Concluído em:  0.00043797492981  Segundos 
Concluído em:  0.000297069549561 Segundos 
Concluído em:  0.000345945358276 Segundos 

Источник

 8
Author: Paulo Costa, 2017-05-23 12:37:34