次のコードを検討してください。
$start = microtime();
for($i = 2; $i < 100; $i++)
{
for($y = 2; $y <= sqrt($i); $y++)
{
if($i%$y != 0)
{
continue;
}
else
{
continue 2;
}
}
echo $i.',';
}
echo "\nFinished in " . (microtime() - $start);
上記のコードが効果的に continue 2 を使用して内側のループを中断し、内側のループの後のコードをスキップすることを考えると、次のコードがより多くのことを行うように見えるのに、平均してより速く実行されるのはなぜですか。
$start = microtime();
for($i = 2; $i < 100; $i++)
{
$flag = true;
for($y = 2; $y <= sqrt($i); $y++)
{
if($i%$y != 0)
{
continue;
}
else
{
$flag = false;
break;
}
}
if($flag === true) echo $i.',';
}
echo "\nFinished in " . (microtime() - $start);
ご意見ありがとうございます。
__ _ __アップデート__ _ __ _ _ __ _ _
フィードバックをお寄せいただきありがとうございます。これが優れたプログラミング手法であるかどうかに関係なく、なぜパフォーマンスの差 (わずかではあるが一貫性がある) が予想したバイアスの範囲内にないのかを理解しようとしていました。
両方のサンプルが同じオーバーヘッドと同じ不正確さで同じ方法を使用して測定されるため、true から microtime への受け渡しは重要ではないように見えます。
平均という言葉の使用によって暗示されるように、複数回の実行がテストされました。
説明のために、microtime() を使用した場合と同じパターンを示す microtime(true) を使用した次の小さなサンプルを検討してください。
これは小さなサンプルですが、パターンは非常に明確です。
続ける
ブレーク 0.00033903121948242 0.00035715103149414 0.00033307075500488 0.00034403800964355 0.00032901763916016
ご覧いただきありがとうございます。さらにフィードバックをお寄せいただきありがとうございます。
__ _ ___ 更新 さらなる調査__ _ __ _ _ _ __
興味深いことに、コードから echo ステートメントを削除すると、continue の実行が速くなり、echo ステートメントを配置すると、break の実行が速くなります。
次のコード サンプルを検討してください。エコー ステートメントが削除されたかどうかによって、結果が競合することを考慮してください。
<?php
$breakStats = array();
$continueStats = array();
ob_start();
for($i = 0; $i < 10000; $i++)
{
$breakStats[] = doBreakTest();
$continueStats[] = doContinueTest();
}
ob_clean();
echo "<br/>Continue Mean " . (array_sum($continueStats) / count($continueStats));
echo "<br/>Break Mean " . (array_sum($breakStats) / count($breakStats));
function doBreakTest()
{
$start = microtime(true);
for($i = 2; $i < 100; $i++)
{
$flag = true;
$root = sqrt($i);
for($y = 2; $y <= $root; $y++)
{
if($i%$y != 0)
{
continue;
}
else
{
$flag = false;
break;
}
}
}
if($flag === true) echo $i . '';
return microtime(true) - $start;
}
function doContinueTest()
{
$start = microtime(true);
for($i = 2; $i < 100; $i++)
{
$root = sqrt($i);
for($y = 2; $y <= $root; $y++)
{
if($i%$y != 0)
{
continue;
}
else
{
echo $i . '';
continue 2;
}
}
}
return microtime(true) - $start;
}
エコーステートメントが存在します:
続行 平均 0.00014134283065796 中断 平均 0.00012669243812561
エコー ステートメントが存在しません:
続行 平均 0.00011746988296509 中断 平均 0.00013022310733795
ブレークとフラグのテストから echo ステートメントを削除することで、($flag === true) チェックも削除することに注意してください。そのため、負荷は軽減されますが、この場合は継続が優先されます。W
そのため、純粋な continue n 対 break + flag のシナリオでは、continue n の方が高速な構造のように見えます。ただし、同数の同一の echo ステートメントと、continue n パフォーマンス フラグを追加します。
これは、論理的には continue n の方が高速であることは理にかなっていますが、存在する echo ステートメントでも同じことが予想されます。
これは明らかに生成されたオペコードの違いであり、エコー ステートメントの位置 (内側のループと外側のループ) は、生成されたオペコードを確認する方法を知っていますか? これは、内部で何が起こっているのかを理解しようとしているときに必要なものだと思います。
ありがとう :)