当使用 aGuid
作为 a 的索引时Dictionary
,是使用对象更好Guid
,还是使用 Guid 的字符串表示形式更好?
我只是重构了一些使用字符串来使用对象的代码,因为到处都有new Guid()
调用。但这让我想知道性能问题可能是什么。(这些集合相当小,但它们会被迭代很多次。)
当使用 aGuid
作为 a 的索引时Dictionary
,是使用对象更好Guid
,还是使用 Guid 的字符串表示形式更好?
我只是重构了一些使用字符串来使用对象的代码,因为到处都有new Guid()
调用。但这让我想知道性能问题可能是什么。(这些集合相当小,但它们会被迭代很多次。)
Guid
应该更快,因为比较更简单 - 只需几个直接字节。该字符串涉及取消引用和更多工作。
当然-您可以配置文件;-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
对象更快,但是如果您将一些输入作为字符串,并且必须在 GUID 的小集合(哈希集)(不经常更改)中搜索它,存储它们可能会更快作为字符串,因为:
要在 GUID 字典中搜索字符串,您必须解析字符串(包括错误检查等)、创建Guid
结构、获取哈希码、进行哈希查找和最后一次 GUID 字节比较。
为了在字符串字典中搜索字符串,您必须构建字符串的哈希(可能比构建Guid
结构更快),查找哈希并进行一个字符串比较。例如,如果您希望集合中没有许多 GUID,则哈希比较通常会失败,您甚至不必进行字符串比较(这比上面第 1 点中的 GUID 比较花费的时间稍长)
如果您已经将 Guid 结构作为输入(例如,因为您对输入字符串进行了一些有效性检查),那么将它们用作字典中的索引当然要好得多。
但是:从设计清晰度的角度来看(这比 99% 的代码中的性能更重要)你应该使用Guid
结构并且只有在你真的遇到性能问题时才改变它(并且分析表明你获得了优势的字符串解决方案)。