2010-01-22 84 views
12

哪個更快?GUID轉換和比較字符串比較有多貴?

bool same=(Guid)Identifier==id; 

bool same=String.Equals(string1,string2, StringComparison.OrdinalIgnoreCase); 
+4

是不是很容易測試? –

+3

類似(但不相同)的問題在這裏http://stackoverflow.com/questions/713109/performance-using-guid-object-or-guid-string-as-key –

+2

什麼時候會這樣嗎?這聽起來像是一種微型優化,應該不惜一切代價避免這種情況。請記住,首先讓它工作,而不是(如果需要)使其更快。 –

回答

26

我用這個代碼:

object victim = Guid.Empty; 
Guid target = Guid.NewGuid(); 

Stopwatch sw = new Stopwatch(); 
sw.Start(); 
for (int i = 0; i < 10000000; i++){ 
    bool equal = ((Guid) victim) == target; 
} 
Console.WriteLine("Direct cast : {0}", sw.Elapsed); 

sw.Reset(); sw.Start(); 
for (int i = 0; i < 10000000; i++) 
{ 
    bool equal = Guid.Equals(victim, target); 
} 
Console.WriteLine("Guid.Equals : {0}", sw.Elapsed); 

sw.Reset(); sw.Start(); 
string a = victim.ToString(); // as suggested by Mikael 
string b = target.ToString(); 
for (int i = 0; i < 10000000; i++) 
{ 
    bool equal = String.Equals(a, b, StringComparison.OrdinalIgnoreCase); 
} 
Console.WriteLine("String.Equals : {0}", sw.Elapsed); 

Console.ReadLine(); 

,得到了這樣的結果對於不同的值(最好的情況):

object victim = Guid.Empty; 
Guid target = Guid.NewGuid(); 
// Direct cast : 00:00:00.1164198 
// Guid.Equals : 00:00:02.1268147 
// String.Equals : 00:00:00.4129527 // oh my! 

而這一結果對於相同的值(糟糕的情況下)

object victim = Guid.Empty; 
Guid target = Guid.Empty; 
// Direct cast : 00:00:00.2793173 
// Guid.Equals : 00:00:03.5625948 
// String.Equals : 00:00:01.7564302 
+1

這是最好的答案,因爲它實際上顯示了一個基準... –

+1

您的基準測試在字節1上進行了比較,這是盡力而爲的。如果你比較更多的字節時間會有更多的不同。 但是時間差異並不像你聲稱的那麼大,因爲你已經在循環中包含了.ToString()。 string a = victim.ToString(); string b = target.ToString(); for(int i = 0; i <10000000; i ++) { bool equal = String.Equals(a,b, StringComparison.OrdinalIgnoreCase); } –

+0

@Mikael,不錯的提示;你的建議會導致string.equals性能的巨大改進。 –

1

一個GUID ==的Guid將使用如下代碼:

public bool Equals(Guid g) 
{ 
if (g._a != this._a) 
{ 
    return false; 
} 
if (g._b != this._b) 
{ 
    return false; 
} 

而串在你的例子比較會使用不安全的指針比較。

沒有基準測試,我懷疑Guid會更快,但我們說的是邊際。而且你真的需要提高數以百萬計的比較數量。

兩個比較都會提前爆發,意味着從左到右,這樣也會影響速度。字符串比較在比較發生之前有更多的檢查,還有一個方法調用。

+0

是什麼讓它更安全? – zsharp

+0

他說速度更快,並不安全,但我很好奇看到不區分大小寫的字符串比較如何使用指針比較。 –

+0

「不安全」的關鍵字不一定是不安全的,但它可以讓你像使用C++一樣使用內存指針。 .Net框架中的許多功能都是以這種方式實現的。所以,這兩種方式都同樣可以放心使用:) 我只是指實際的功能在框架 - 私有靜態不安全INT CompareOrdinalIgnoreCaseHelper(STRA字符串,字符串STRB) –

1

GUID比較是一個16字節的memcmp。它不會比字符串比較糟糕,但如果你關心性能,你不應該使用託管代碼。

+0

他的字符串比較是不區分大小寫的。儘管時間上的比較應該不會有太大的不同,但它並不像Guid那樣是逐字節的比較。 –

+0

不是。 .net guid由Int32 + Int16 + Int16 +(字節* 8)組成。它會比較一個到另一個,直到最後一個字節。意思是最多11次比較。 –

+0

託管代碼實際上非常快 - 比我上次檢查的C++慢25-50%左右,與Java相同......比較Python/Ruby比較慢8,000%,PHP比慢5萬... –

10

在我做一個UUID-UUID比較VS String-String比較的測試中,UUID比較大約需要1/4的時間作爲字符串比較。

但是,String-> UUID的投射很昂貴。比UUID->字符串轉換貴得多。兩者都比任何一種比較方法都貴。

因此: 如果您有兩個UUID直接比較UUID。 如果你有兩個字符串直接比較字符串。 如果您有一個字符串和一個UUID,請將UUID轉換爲字符串並比較字符串。

1

.NET Guid是一個16字節的結構,當以字符串形式表示時,將以此模式格式化「xxxxxxxx-xxxx- xxxx-xxxx-xxxxxxxxxxxx「,大約32個字符。

所以表示爲GUID需要16個字節, 表示爲一個字符串,需要32 * 2 = 64個字節。

因此GUID.Equals()應該表現更好。

此外,GUID.Equals(GUID)將執行更好,然後guid1 == guid2,因爲前者沒有涉及拳擊。

+1

'Guid.Equals(object,object)'所以你會有un/boxing參與;請在那裏看到我的基準 –

+0

Guid.Equals(Guid)在這裏描述。 http://msdn.microsoft.com/en-us/library/asw89aw8.aspx。看起來像這個過載沒有涉及拳擊。 – Santhosh

+0

對不起,我以爲你在談論靜態版本;但是,無論如何,你需要使用Guid.Equals(對象)作爲整體關於從對象投射 –