2010-01-22 50 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(对象)作为整体关于从对象投射 –