人們喜歡優化。它們很容易理解,很容易應用…。但不久前,在查看Twig的pull請求時,我讀到一篇關於PHP中三元運算子效能的有趣討論。
你知道下面哪個片段是最快的嗎(當然,它們做的是完全一樣的)?
// snippet 1 $tmp = isset($context['test']) ? $context['test'] : ''; // snippet 2 if (isset($context['test'])) { $tmp = $context['test']; } else { $tmp = ''; }
正確的答案是:
視情況而定。大多數時候,它們的速度是一樣的,你不需要在意。但是如果$context['test']包含大量數據,那麼snippet 2要比snippet 1快得多。
下面是我用來測試不同場景的程式碼:
$context = array('test' => true); // optionally fill-in the test value with lots of data for ($i = 0; $i < 100000; $i++) { $context['test'][$i] = $i; } // you can also just create a big string // $context = str_repeat(' ', 1000000); // benchmark $time = microtime(true); for ($i = 0; $i < 100; $i++) { // the snippet of code to benchmark $tmp = isset($context['test']) ? $context['test'] : ''; } printf("TIME: %0.2d\n", (microtime(true) - $time) * 1000);
注意,這裡的絕對效能數字沒有意義。我們只是想比較不同片段之間的速度。
在我的筆記型電腦上,snippet 1的運行時間超過2秒,而snippet 2的運行時間約為0.05ms。這是很大的不同!但是如果要測試的變數沒有承載很多數據,那麼速度幾乎是一樣的。
那麼,為什麼三元運算子在某些情況下會變慢呢?為什麼它依賴於儲存在測試變數中的值?
答案非常簡單:
#三元運算子總是複製值,而if語句不複製值。為什麼?因為PHP使用了一種稱為寫入時複製的技術:在為變數賦值時,PHP實際上不會創建變數內容的副本,直到對其進行修改。
當您寫像$tmp = $context['test']這樣的語句時,幾乎不會發生什麼:$tmp變數只是成為$context['test']變數的引用;這就是為什麼它非常快。但一旦你想修改變量,PHP需要複製原始的一個:
$tmp = $context['test']; // the copy happens now $tmp[] = true; // copy also happens if the original variable changes // $context['test'][] = true;
#綜上所述,三元運算子的速度與複製語句結果所花費的時間直接相關,即使不是嚴格需要。複製100000個元素的陣列需要時間。
如果您使用的是PHP 5.3,那麼有一個更簡單的方法可以使用新的?:construct:來表達我們的語句:
$tmp = $context['test'] ?: '';
不過就效能而言,這個新構造與標準構造具有相同的缺點,即使PHP可能能夠最佳化變數存在的情況。
以上是PHP三元運算子:快還是不快?的詳細內容。更多資訊請關注PHP中文網其他相關文章!