偶然看到<C#中判斷空字符串的3種方法性能分析 >作者:清清月兒 主頁:http://blog.csdn.net/21aspnet/ 時間:2007.4.28
寫的一篇關於字符串爲空判斷方法的性能分析文章,實驗結果作者已經給出,結論是使用.length==0判斷的效率最高,但是文章的結尾只有一句話,感覺不夠詳細,所以自己寫下這個文章,算一個補充和學習吧。
【1】程序代碼執行的硬件環境:
CPU |
Intel T2300 1.66GHz |
內存 |
Kingston DDR2 667 1G |
硬盤 |
80G 5400轉 8m |
測試的軟件環境:
OS |
Windows XP Pro |
IDE |
VS 2008 RTM |
【2】測試的代碼如下:
定義了3個變量,分別調用4種方法,進行100w次判斷,記錄測試時間:
Stopwatch sw = new Stopwatch();//實例化一個對象,記錄時間
string sEmpty1 = string.Empty;//實例化3個字符串對象,賦值如下。分別作空比較試驗
string sEmpty2 = "";
string sEmpty3 = "StringNotEmpty";
////////////////////////////////////////////////////Test sEmpty1///////////////////////////
sw.Start();//開始記錄
for (int i = 0; i <= 1000000; i++)
{
if (sEmpty1.Length == 0)
{ }
}
sw.Stop();//停止記錄時間
Console.WriteLine("string.Empty Length == 0 Time Cost is {0}", sw.ElapsedMilliseconds);
////////
sw.Reset();//重置計數器爲0;
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if (sEmpty1 == "")
{ }
}
sw.Stop();
Console.WriteLine("string.Empty == \"\" Time Cost is {0}", sw.ElapsedMilliseconds);
////
sw.Reset();
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if (sEmpty1 == string.Empty)
{ }
}
sw.Stop();
Console.WriteLine("string.Empty == string.Empty Time Cost is {0}", sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if(string.IsNullOrEmpty(sEmpty1))
{}
}
sw.Stop();
Console.WriteLine("string.IsNullOrEmpty Time Cost is {0}", sw.ElapsedMilliseconds);
Console.WriteLine();
////////////////////////////////////////////////////Test sEmpty2///////////////////////////
sw.Reset();
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if(sEmpty2.Length == 0)
{}
}
sw.Stop();
Console.WriteLine("\"\" Length == 0 Time Cost is {0}", sw.ElapsedMilliseconds);
////////
sw.Reset();
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if(sEmpty2 == "")
{}
}
sw.Stop();
Console.WriteLine("\"\" == \"\" Time Cost is {0}", sw.ElapsedMilliseconds);
/////
sw.Reset();
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if(sEmpty2 == string.Empty)
{}
}
sw.Stop();
Console.WriteLine("\"\" == string.Empty Test3 Time Cost is {0}", sw.ElapsedMilliseconds);
/////
sw.Reset();
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if(string.IsNullOrEmpty(sEmpty2))
{}
}
sw.Stop();
Console.WriteLine("\"\" string.IsNullOrEmpty Time Cost is {0}", sw.ElapsedMilliseconds);
Console.WriteLine();
////////////////////////////////////////////////////Test sEmpty3///////////////////////////
sw.Reset();
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if(sEmpty3.Length == 0)
{}
}
sw.Stop();
Console.WriteLine("\"StringNotEmpty\" Length == 0 Time Cost is {0}", sw.ElapsedMilliseconds);
////////
sw.Reset();
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if(sEmpty3 == "")
{}
}
sw.Stop();
Console.WriteLine("\"StringNotEmpty\" == \"\" Time Cost is {0}", sw.ElapsedMilliseconds);
////
sw.Reset();
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if(sEmpty3 == string.Empty)
{}
}
sw.Stop();
Console.WriteLine("\"StringNotEmpty\" == string.Empty Test3 Time Cost is {0}", sw.ElapsedMilliseconds);
////
sw.Reset();
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if(string.IsNullOrEmpty(sEmpty3))
{}
}
sw.Stop();
Console.WriteLine("\"StringNotEmpty\" IsNullOrEmpty Time Cost is {0}", sw.ElapsedMilliseconds);
string sEmpty1 = string.Empty;//實例化3個字符串對象,賦值如下。分別作空比較試驗
string sEmpty2 = "";
string sEmpty3 = "StringNotEmpty";
////////////////////////////////////////////////////Test sEmpty1///////////////////////////
sw.Start();//開始記錄
for (int i = 0; i <= 1000000; i++)
{
if (sEmpty1.Length == 0)
{ }
}
sw.Stop();//停止記錄時間
Console.WriteLine("string.Empty Length == 0 Time Cost is {0}", sw.ElapsedMilliseconds);
////////
sw.Reset();//重置計數器爲0;
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if (sEmpty1 == "")
{ }
}
sw.Stop();
Console.WriteLine("string.Empty == \"\" Time Cost is {0}", sw.ElapsedMilliseconds);
////
sw.Reset();
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if (sEmpty1 == string.Empty)
{ }
}
sw.Stop();
Console.WriteLine("string.Empty == string.Empty Time Cost is {0}", sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if(string.IsNullOrEmpty(sEmpty1))
{}
}
sw.Stop();
Console.WriteLine("string.IsNullOrEmpty Time Cost is {0}", sw.ElapsedMilliseconds);
Console.WriteLine();
////////////////////////////////////////////////////Test sEmpty2///////////////////////////
sw.Reset();
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if(sEmpty2.Length == 0)
{}
}
sw.Stop();
Console.WriteLine("\"\" Length == 0 Time Cost is {0}", sw.ElapsedMilliseconds);
////////
sw.Reset();
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if(sEmpty2 == "")
{}
}
sw.Stop();
Console.WriteLine("\"\" == \"\" Time Cost is {0}", sw.ElapsedMilliseconds);
/////
sw.Reset();
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if(sEmpty2 == string.Empty)
{}
}
sw.Stop();
Console.WriteLine("\"\" == string.Empty Test3 Time Cost is {0}", sw.ElapsedMilliseconds);
/////
sw.Reset();
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if(string.IsNullOrEmpty(sEmpty2))
{}
}
sw.Stop();
Console.WriteLine("\"\" string.IsNullOrEmpty Time Cost is {0}", sw.ElapsedMilliseconds);
Console.WriteLine();
////////////////////////////////////////////////////Test sEmpty3///////////////////////////
sw.Reset();
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if(sEmpty3.Length == 0)
{}
}
sw.Stop();
Console.WriteLine("\"StringNotEmpty\" Length == 0 Time Cost is {0}", sw.ElapsedMilliseconds);
////////
sw.Reset();
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if(sEmpty3 == "")
{}
}
sw.Stop();
Console.WriteLine("\"StringNotEmpty\" == \"\" Time Cost is {0}", sw.ElapsedMilliseconds);
////
sw.Reset();
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if(sEmpty3 == string.Empty)
{}
}
sw.Stop();
Console.WriteLine("\"StringNotEmpty\" == string.Empty Test3 Time Cost is {0}", sw.ElapsedMilliseconds);
////
sw.Reset();
sw.Start();
for (int i = 0; i <= 1000000; i++)
{
if(string.IsNullOrEmpty(sEmpty3))
{}
}
sw.Stop();
Console.WriteLine("\"StringNotEmpty\" IsNullOrEmpty Time Cost is {0}", sw.ElapsedMilliseconds);
代碼的運行結果如下:
結果分析來看,調用string的length==0作比較,不論字符串是否爲空,此方法的效率最高,此點與清清月兒的結果一致;
string的isNullOrEmpty()方法的效率基本不變,無論字符串是否有值;
== string.Empty和== ""兩種方法在3個變量測試的實驗中效率相對較低,但是兩者再和對方比較的時候會出現效率降低的情況,見上圖;
【3】原因剖析:
原因是什麼呢?我們來看看對應的il代碼:
1.locals init ([0] class [System]System.Diagnostics.Stopwatch sw,
2 [1] string sEmpty1,
3 [2] string sEmpty2,
4 [3] string sEmpty3,
5 [4] int32 i,
6 [5] bool CS$4$0000)
7 IL_0000: nop
8 IL_0001: newobj instance void [System]System.Diagnostics.Stopwatch::.ctor()
9 IL_0006: stloc.0
10 IL_0007: ldsfld string [mscorlib]System.String::Empty//將指定字段的值推送到堆棧上。 ldsfld 指令將靜態(在類的所有實例中共享)字段的值推送到堆棧上。返回類型是與傳遞的元數據標記 field 關聯的類型。
11
12 IL_000c: stloc.1
13 IL_000d: ldstr ""//將對字符串的對象引用推送到堆棧上,ldstr 指令推送對錶示在元數據中存儲的特定字符串的新字符串對象的對象引用(O 類型)。
14 IL_0012: stloc.2
15 IL_0013: ldstr "StringNotEmpty"//將對字符串的對象引用推送到堆棧上,ldstr 指令推送對錶示在元數據中存儲的特定字符串的新字符串對象的對象引用(O 類型)。
16 IL_0018: stloc.3
17 IL_0019: ldloc.0
2 [1] string sEmpty1,
3 [2] string sEmpty2,
4 [3] string sEmpty3,
5 [4] int32 i,
6 [5] bool CS$4$0000)
7 IL_0000: nop
8 IL_0001: newobj instance void [System]System.Diagnostics.Stopwatch::.ctor()
9 IL_0006: stloc.0
10 IL_0007: ldsfld string [mscorlib]System.String::Empty//將指定字段的值推送到堆棧上。 ldsfld 指令將靜態(在類的所有實例中共享)字段的值推送到堆棧上。返回類型是與傳遞的元數據標記 field 關聯的類型。
11
12 IL_000c: stloc.1
13 IL_000d: ldstr ""//將對字符串的對象引用推送到堆棧上,ldstr 指令推送對錶示在元數據中存儲的特定字符串的新字符串對象的對象引用(O 類型)。
14 IL_0012: stloc.2
15 IL_0013: ldstr "StringNotEmpty"//將對字符串的對象引用推送到堆棧上,ldstr 指令推送對錶示在元數據中存儲的特定字符串的新字符串對象的對象引用(O 類型)。
16 IL_0018: stloc.3
17 IL_0019: ldloc.0
兩者的差別由於推送到堆棧上的內容不同,前者是靜態共享值推送到堆棧,後者是字符串對象的地址推送到堆棧.
造成的比較差別.另外字符串值是否相等的資料大家可以看看園子裏緣清的文章,有很好的參考價值.地址:http://www.cnblogs.com/isline/archive/2009/02/04/1383799.html.希望大家一起交流!