最近在學php,看php手冊的時候,突然間對if和switch的性能差別有興趣,在網上查了不少資料,最後看到這篇文章,終於讓我發現平時在寫代碼的進候的一個錯誤,喜歡用if ..else多於switch,實際上switch的性能要比if ..else高多了.特引用此文於此,以後寫代碼時候多多注意.
記得在很久以前,博客園上一個哥們抱怨.net的源碼寫的太爛,到處都是switch,我當時就做過一個測試,證實了switch比if性能高許多。今天又看見這個話題,呵呵,那就再做個測試吧。
代碼:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static Int32 Count = 100000000;
static Int32 TestIfElse(Int32 value)
{
Int32 i = 0;
Stopwatch sw = new Stopwatch();
sw.Start();
for (int j = 0; j < Count; j++ )
{
if (value == 1)
i += 1;
else if (value == 2)
i += 2;
else if (value == 3)
i += 3;
else if (value == 4)
i += 4;
else if (value == 5)
i += 5;
}
sw.Stop();
Console.WriteLine("TestIfElse: " + sw.ElapsedMilliseconds);
return i;
}
static Int32 TestSwitch(Int32 value)
{
Int32 i = 0;
Stopwatch sw = new Stopwatch();
sw.Start();
for (int j = 0; j < Count; j++)
{
switch (value)
{
case 1:
i+=1;
break;
case 2:
i+=2;
break;
case 3:
i+=3;
break;
case 4:
i+=4;
break;
case 5:
i+=5;
break;
default:
break;
}
}
sw.Stop();
Console.WriteLine("TestSwitch: " + sw.ElapsedMilliseconds);
return i;
}
static void Main(string[] args)
{
TestIfElse(5);
TestSwitch(5);
Console.Read();
}
}
}
release下編譯,測試結果:
TestIfElse: 613
TestSwitch: 165
4倍左右的性能差距。反編譯看il,會發現TestSwitch方法中多了這麼一句:
switch (L_0032, L_0038, L_003e, L_0044, L_004a)
這句話實現了一個 jump table。
正如一線工作者 所言,這個switch 指令是一個有索引的跳轉,而if ... else 是無索引的跳轉。if...else 是 O(N)級別的,switch ... case 是 O(1)級別的。
如果將上面測試代碼的分支增加到10支,測試TestSwitch(10)與TestIfElse(10)的性能,會發現前者比後者幾乎快7-8倍。
詳細解釋請參見《深入理解計算機系統》一書中的某章(忘了哪個章節,書不在身邊,裏面講了switch和if的區別)。也可參考這篇文章:http://www.9php.com/FAQ/cxsjl/c/2008/10/1435098132356.html。.net下的分析見:http://www.cnblogs.com/yeah/archive/2009/02/16/1392094.html
如果switch(String ..),測試了一下,switch與if...else性能相當。我原以爲爲是無法生成跳轉表,剛看完http://www.cnblogs.com/yeah/archive/2009/02/16/1392094.html這篇文章,發現還是可以生成跳轉表,只是這個跳轉表的代價比簡單的整數類型的跳轉表代價高。也就是說,這種情況下,switch case 還是O(1)級別分支語句的。