作者測試了四種雙層迴圈寫法,結果令人驚訝:
| 方式 | 程式碼片段 | 耗時 |
|---|---|---|
| 方式一 | while(++$i < 10000) { while(++$j < 10000); } | 16 秒 |
| 方式二 | while($i < 10000) { while($j < 10000) ++$j; ++$i; } | 13 秒 |
| 方式三 | while($i < 10000) { while($j < 10000) $j++; $i++; } | 15 秒 |
| 方式四 | while($i++ < 10000) { while($j++ < 10000); } | 13 秒 |
// 方式一:遞增在條件判斷中
while(++$i < 10000) { ... }
// PHP 必須取得 ++$i 的「回傳值」來比較
// → 產生 IS_VAR 存放結果 → 較慢
// 方式二:遞增在迴圈體內
while($i < 10000) { ... ++$i; }
// $i 全程保持 IS_CV
// ++$i 不需回傳值 → 直接操作 IS_CV → 最快
$i++ 雖不需回傳值,但後置遞增語意要求「回傳舊值、再自增」,Zend Engine 內部仍需建立暫存副本,故比前置遞增略慢(15s vs 13s)。
while($i++ < 10000) { ... }
// 需將 $i 原值存入 IS_TMP_VAR 供比較
// IS_TMP_VAR 存取比 IS_VAR 更慢
// 但測試卻是 13s?可能受測試環境、OpCache 優化影響,實際差異極小。
++$i:避免建立暫存變數,語意更清晰。php -dvld.active=1 -dvld.execute=0 your_script.php
// 需安裝 vld 擴展:pecl install vld
觀察 ZEND_PRE_INC、ZEND_POST_INC、ZEND_IS_SMALLER 等 opcode 的運算元類型 (IS_CV/IS_VAR/IS_TMP_VAR)。