php - 继续状态的表现
php - performance of continue state
我今天在工作时在想:有没有使用 continue
状态更快地获得结果的方法?
for ($i=0; $i<5000; $i++) {
if (!($i % 2)) {
continue;
}
do_something_odd($i);
}
是使用 if/else 的普通循环更快还是使用 continue 跳过结果更快?
我问是因为性能和优化。
无论如何,不确定您是否仍在寻找答案:
总的来说,两者之间没有性能差异:
for (...) {
if (condition) continue;
some work;
}
和
for (...) {
if (!condition) some work;
}
我建议避免continue
,只是因为我认为它的可读性较差,基本上是goto
。
当然首先要优化的是高层算法,数据结构等等。如果你完成了它并且你需要最大化性能 - 主要敌人是 condition/branch 和错误预测。有许多不同的技术:
- 如果可能,将条件移出循环
- 将循环拆分为多个循环
- 与按位运算符相比,乘法、除法和模运算通常非常慢
- 部分条件可以用无分支语句代替
- 取消循环以减少测试次数
衡量每一个变化
例如,稍微修改您的代码版本以计算 [-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 秒
应用第一条和第二条规则:
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 秒
我今天在工作时在想:有没有使用 continue
状态更快地获得结果的方法?
for ($i=0; $i<5000; $i++) {
if (!($i % 2)) {
continue;
}
do_something_odd($i);
}
是使用 if/else 的普通循环更快还是使用 continue 跳过结果更快?
我问是因为性能和优化。
无论如何,不确定您是否仍在寻找答案:
总的来说,两者之间没有性能差异:
for (...) {
if (condition) continue;
some work;
}
和
for (...) {
if (!condition) some work;
}
我建议避免continue
,只是因为我认为它的可读性较差,基本上是goto
。
当然首先要优化的是高层算法,数据结构等等。如果你完成了它并且你需要最大化性能 - 主要敌人是 condition/branch 和错误预测。有许多不同的技术:
- 如果可能,将条件移出循环
- 将循环拆分为多个循环
- 与按位运算符相比,乘法、除法和模运算通常非常慢
- 部分条件可以用无分支语句代替
- 取消循环以减少测试次数
衡量每一个变化
例如,稍微修改您的代码版本以计算 [-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 秒
应用第一条和第二条规则:
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 秒