Я думал сегодня на работе: есть ли гораздо более быстрый способ получить результаты, используя continue
государство?
for ($i=0; $i<5000; $i++) {
if (!($i % 2)) {
continue;
}
do_something_odd($i);
}
Скорее обычная петля с если еще или быстрее пропустить результаты, используя продолжить?
Я спрашиваю, потому что производительность и оптимизация.
Во всяком случае, не уверен, что вы все еще ищете ответ:
в общем, нет разницы в производительности между:
for (...) {
if (condition) continue;
some work;
}
а также
for (...) {
if (!condition) some work;
}
Предлагаю избежать continue
только потому, что я думаю, что это менее читабельно, это в основном goto
,
Конечно, первое, что нужно оптимизировать, — это алгоритмы высокого уровня, структура данных и так далее. Если вы покончили с этим и вам нужно максимизировать производительность — главный враг — это условие / ветвь и неправильные прогнозы. Для этого есть много разных техник:
Мера каждое изменение
Например, слегка измененная версия вашего кода для вычисления количества четных и нечетных чисел в диапазоне [-N, N], исключая 0:
define('N', 100000000);
$start = microtime(true);
$odd_count = 0;
$even_count = 0;
for ($i=-N; $i<=N; $i++)
if ($i != 0)
if ($i % 2 != 0) $odd_count++;
else $even_count++;
$end = microtime(true);
echo 'odd: '.$odd_count."\n";
echo 'even: '.$even_count."\n";
echo 'time: '.($end-$start)."\n";
Конечно, мы можем заменить весь этот цикл простой формулой (это оптимизация алгоритма высокого уровня), но давайте попробуем поработать с циклом:
Среднее время на моем хосте за несколько прогонов: 9,1 с
Применить 1-е и 2-е правило:
for ($i=-N; $i<0; $i++)
if ($i % 2 != 0) $odd_count++;
else $even_count++;
for ($i=1; $i<=N; $i++)
if ($i % 2 != 0) $odd_count++;
else $even_count++;
Время: 7,7 с
Применить 3-е и 4-е правило:
for ($i=-N; $i<0; $i++) {
$t = $i & 1;
$odd_count += $t;
$even_count += 1 - $t;
}
for ($i=1; $i<=N; $i++) {
$t = $i & 1;
$odd_count += $t;
$even_count += 1 - $t;
}
Время: 7,3 сек
И конечный результат:
for ($i=-N; $i<0;) {
$t = $i++ & 1; $odd_count += $t; $even_count += 1 - $t;
$t = $i++ & 1; $odd_count += $t; $even_count += 1 - $t;
$t = $i++ & 1; $odd_count += $t; $even_count += 1 - $t;
$t = $i++ & 1; $odd_count += $t; $even_count += 1 - $t;
}
for ($i=1; $i<=N;) {
$t = $i++ & 1; $odd_count += $t; $even_count += 1 - $t;
$t = $i++ & 1; $odd_count += $t; $even_count += 1 - $t;
$t = $i++ & 1; $odd_count += $t; $even_count += 1 - $t;
$t = $i++ & 1; $odd_count += $t; $even_count += 1 - $t;
}
Время: 7,0 сек
Других решений пока нет …