Который имеет лучшую производительность? For или Foreach,+Range?
две формы ниже, который имеет лучшую производительность?
-
For
:for( $x=1; $x < 31; $x++ ) echo $x . PHP_EOL;
-
Foreach
+range
:foreach( range(1,30) as $x ) echo $x . PHP_EOL;
я Знаю, что разница, вероятно, будет в миллисекундах, но это стоит изучения, так как в приложение с большой трафик, эти миллисекунды могут сделать разницу.
, Если существует третий способ еще более высокой производительности, пожалуйста, выберите.
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 элементов, например, доступ к элементам более ранних или более поздних версий в текущей итерации. Уже Генераторы, используйте в ситуациях, где требуется устранить ограничения памяти.
Мое личное мнение, использовать то, что имеет смысл в контексте. Разница во времени будет минимальной, в большинстве случаев.
Большая вещь, чтобы отметить:
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