C# 性能 - 使用 Guid 对象或 Guid 字符串作为 Key
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/713109/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Performance - using Guid object or Guid string as Key
提问by Benjol
When using a Guid
as an index for a Dictionary
, is it better to use the Guid
object, or the string representation of the Guid?
当使用 aGuid
作为a的索引时Dictionary
,使用Guid
对象还是使用Guid 的字符串表示更好?
I just refactored some code which was using string to use the object, because there were new Guid()
calls all over the place. But that left me wondering what the performance issues might be. (The collections are fairly small, but they get iterated lots of times.)
我只是重构了一些使用字符串来使用对象的代码,因为到处都有new Guid()
调用。但这让我想知道性能问题可能是什么。(集合相当小,但它们被迭代了很多次。)
采纳答案by Marc Gravell
The Guid
should be quicker, as the comparison is simpler - just a few direct bytes. The string involves a dereference and lots more work.
本Guid
应更快,因为比较简单-只是几个直接字节。该字符串涉及取消引用和更多工作。
Of course - you could profile ;-p
当然 - 你可以配置文件;-p
Evidence:
证据:
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
based on:
基于:
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();
}
}
回答by Richard
The collections are fairly small, but they get iterated lots of times
集合相当小,但它们被迭代了很多次
If you are iterating, there are no key to key comparisons. If you are adding/modifying or looking up by key, then keys will be hashed and the hashes compared; only if the hashes are equal will the keys be compared.
如果您正在迭代,则没有关键比较的关键。如果您通过键添加/修改或查找,则键将被散列并比较散列;只有当哈希值相等时,才会比较键。
Therefore, unless you are performing a lot of key based operations on huge dictionaries with many hash collisions the speed of key to key comparisons will not be a major factor.
因此,除非您对具有许多散列冲突的庞大字典执行大量基于键的操作,否则键对键比较的速度将不是主要因素。
回答by MartinStettner
My first thought would have been, that Guid
objects are faster, but if you get some input as string and have to search it in a small collection (hashset) of GUIDs (which aren't changing often), it might be faster to store them as strings, because:
我的第一个想法是,该Guid
对象更快,但是如果您以字符串形式获取一些输入并且必须在一个小的 GUID 集合(哈希集)中搜索它(不经常更改),则存储它们可能会更快作为字符串,因为:
For searching a string in a GUID-Dictionary, you have to parse the string (including error checking etc.), create the
Guid
structure, get the hash code, do the hash lookup and one final comparison of the GUID bytes.For searching a string in a String-Dictionary, you have to build the hash of the string (possibly faster than building the
Guid
struct), lookup the hash and do one string comparison. If, for instance, you expect many GUIDs not to be in the collections, the hash comparison will fail often an you don't even have to do the string comparison (which takes slightly more time than the GUID-comparison from point 1 above)
要在 GUID 字典中搜索字符串,您必须解析字符串(包括错误检查等)、创建
Guid
结构、获取哈希代码、进行哈希查找和对 GUID 字节进行最终比较。要在字符串字典中搜索字符串,您必须构建字符串的散列(可能比构建
Guid
结构更快),查找散列并进行一次字符串比较。例如,如果您希望许多 GUID 不在集合中,那么哈希比较通常会失败,您甚至不必进行字符串比较(这比上面第 1 点的 GUID 比较花费的时间略多)
If you already have Guid-structures as input (e.g. because you did some validity-checking on the input strings) of course it's far better to reuse them as index in the dictionary.
如果您已经有 Guid 结构作为输入(例如,因为您对输入字符串进行了一些有效性检查),当然最好将它们作为字典中的索引重用。
BUT: From point of view of design clarity (which is far more important than performance in 99% of all code) you should use Guid
structures and only change that, if you really run into performance troubles (and profiling shows that you get an advantage out of the string solution).
但是:从设计清晰度的角度来看(这在 99% 的代码中比性能重要得多)你应该使用Guid
结构并且只有在你真的遇到性能问题时才改变它(并且分析表明你获得了优势)的字符串解决方案)。