性能 – 使用Guid对象或Guidstring作为键

当使用Guid作为Dictionary的索引时,使用Guid对象还是使用Guid的string表示更好?

我只是重构了一些使用string来使用对象的代码,因为在那里有new Guid()调用。 但是这让我想知道性能问题可能是什么。 (集合相当小,但是它们迭代很多次。)

Guid应该更快,因为比较比较简单 – 只有几个直接字节。 string涉及解除引用和更多的工作。

当然 – 你可以剖析; – P

证据:

 Searching for 7f9b349f-f36f-94de-ad96-04279ddf6ecf As guid: 466; -1018643328 As string: 512; -1018643328 Searching for 870ba465-08f2-c872-cfc9-b3cc1ffa09de As guid: 470; 1047183104 As string: 589; 1047183104 Searching for d2376f8a-b8c9-4633-ee8e-9679bb30f918 As guid: 423; 1841649088 As string: 493; 1841649088 Searching for 599889e8-d5fd-3618-4c4f-cb620e6f81bb As guid: 488; -589561792 As string: 493; -589561792 Searching for fb64821e-c541-45f4-0fd6-1c772189dadf As guid: 450; 1389733504 As string: 511; 1389733504 Searching for 798b9fe5-ba15-2753-357a-7637161ee48a As guid: 415; 779298176 As string: 504; 779298176 Searching for 12ba292e-8e59-e5d0-7d04-e811a237dc21 As guid: 457; 558250944 As string: 564; 558250944 Searching for 05b3ce14-dfbf-4d3a-1503-ced515decb81 As guid: 413; 1658205056 As string: 504; 1658205056 Searching for 8db4a556-0a65-d8cb-4d0d-0104245d18b8 As guid: 415; 696231936 As string: 506; 696231936 Searching for c49cf80c-5537-fba5-eebd-8ad21bba09c4 As guid: 459; 2100976384 As string: 557; 2100976384 

基于:

 using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; static class Program { static void Main() { Random rand = new Random(123456); int COUNT = 1000; Dictionary<Guid, int> guids = new Dictionary<Guid, int>(COUNT); Dictionary<string, int> strings = new Dictionary<string, int>( COUNT, StringComparer.Ordinal); byte[] buffer = new byte[16]; for (int i = 0; i < COUNT; i++) { rand.NextBytes(buffer); Guid guid = new Guid(buffer); int val = rand.Next(); guids.Add(guid, val); strings.Add(guid.ToString(), val); } for(int i = 0 ; i < 10 ; i++) { int index = rand.Next(COUNT); Guid guid = guids.Keys.Skip(index).First(); Console.WriteLine("Searching for " + guid); int chk = 0; const int LOOP = 5000000; Stopwatch watch = Stopwatch.StartNew(); for (int j = 0; j < LOOP; j++) { chk += guids[guid]; } watch.Stop(); Console.WriteLine("As guid: " + watch.ElapsedMilliseconds + "; " + chk); string key = guid.ToString(); chk = 0; watch = Stopwatch.StartNew(); for (int j = 0; j < LOOP; j++) { chk += strings[key]; } watch.Stop(); Console.WriteLine("As string: " + watch.ElapsedMilliseconds + "; " + chk); } Console.ReadLine(); } } 

收集是相当小的,但他们迭代了很多次

如果您正在迭代,则没有键比较的关键。 如果你正在添加/修改或按键查找,那么键将被散列和散列比较; 只有当散列相等时才能比较键。

因此,除非你在大量字典上进行大量的基于密钥的操作,而且有很多散列冲突,否则密钥比较的关键速度将不是主要因素。

我的第一个想法是, Guid对象更快,但是如果你得到一些string的input,并且需要在GUID的一个小集合(hashset)中进行search(通常不会经常改变),那么存储他们作为string,因为:

  • 为了在一个GUID字典中search一个string,你必须parsingstring(包括错误检查等),创buildGuid结构,获得哈希码,完成哈希查找和GUID字节的最后一个比较。

  • 为了在一个string字典中search一个string,你必须build立string的散列(可能比构buildGuid结构更快),查找散列并进行一个string比较。 例如,如果您希望许多GUID不在集合中,则哈希比较常常会失败,您甚至不必进行string比较(比上面第1点的GUID比较花费的时间稍多)

如果你已经有了Guid结构作为input(例如,因为你对inputstring进行了一些有效性检查),当然,重用它们作为字典中的索引要好得多。

但是 :从devise清晰度的angular度来看(这比99%的代码中的性能要重要得多),你应该使用Guid结构,只有改变了这一点,如果你真的遇到了性能问题(分析表明你有优势出string解决scheme)。