当前位置: 首页 > 知识库问答 >
问题:

使用以KeyValuePair作为密钥的字典(C#.NET)的性能非常糟糕

平学
2023-03-14

在我正在编写的一个应用程序中,我有两个潜在的大数据集需要相互映射。一个是从Web服务返回的List,一个是DataTable。我需要为列表中的每个项目获取ANSI(或ISO)编号,并找到包含该ANSI编号的数据表行,然后对其进行处理。

自从DataTable。Select非常慢,我必须对列表中的每一项都这样做,我尝试了更快的替代方案。请记住,DataTable对象没有数据库。所以我不能利用任何SQL功能或类似的功能。

我认为最快的方法可能是创建一个带有KeyValuePair(a:Ansi编号或I:Iso编号)的字典,并将其用作密钥。该值将是该行的其余部分。创建字典显然需要一点处理时间,但是我可以利用字典的极快搜索时间来找到我需要的每一行,然后将这些行添加回表中。因此,在foreach循环中,对于列表,我的复杂性只有O(1),而不是O(n)或任何数据表。选择有。

令我惊讶的是,这本词典的速度太慢了。我不明白为什么,直到我发现使用字符串(只是ANSI数字)而不是KeyValuePair显著提高了性能。我说话快了几百倍。这到底是怎么可能的?以下是我的测试方法:

我生成了一个模拟web服务输出的列表。我基于该列表创建了一个字典,其中包含一个键(string或KeyValuePair)和一个DataRow作为值。我对该列表进行foreach循环,在字典中搜索该列表中的每个项目,然后为返回的DataRow赋值。就这样。

如果我使用KeyValuePair作为键来访问字典,那么1000个条目需要几秒钟的时间;如果我将字典修改为只使用字符串作为键,那么10000个条目需要几毫秒的时间。仅供参考:我设计了这个测试,所以总是会有点击,所以所有的键都会被找到。

这是我正在测量时间的代码块:

foreach(ProductList.Products item in pList.Output.Products)
{
   //KeyValuePair<string, string> kv = new KeyValuePair<string, string>("A", item.Ansi);
   DataRow row = dict[item.Ansi];
   for (int i = 0; i < 10; i++)
   {
      row["Material"] = item.Material + "a"; //Do stuff just for debugging
   }
   hits++;
}

那么,如果我使用字典(KeyValuePair,DataRow)而不是字典(String,DataRow),执行时间怎么可能突然变长数百倍呢?

共有2个答案

施自明
2023-03-14

您可能会遇到大量与键值对的哈希冲突。可以使用GetHashCode进行测试。

下面的链接是元组,但我高度怀疑你有同样的事情与键值对. gethashcode-High-rate-of-重复我将标记为重复,但你们许多人有其他事情发生。

在此链接中,Microsoft建议不要对密钥使用值类型。KVP的GetHashCode继承自值类型。

慕翰学
2023-03-14

KeyValuePair

这并不奇怪,因为这不是什么KeyValuePair

如果不想使用自己的结构,请使用Tuple。但是我真的只是为任何一种坚持创造我自己的结构,真的。

作为旁注,DataTable。Select实际上非常快,因为它是为过滤输出数据而设计的。不过,它并不是真正为在循环中被调用数百次而设计的——开销占主导地位。当然,这假设您有适当的索引。在你的情况下,我认为每次调用Select时都会重新生成索引,这有点慢:)

 类似资料:
  • 问题内容: Python不允许将字典用作其他字典中的键。有使用非嵌套字典作为键的解决方法吗? 问题答案: 如果您有一本真正不变的字典(尽管我不清楚为什么不只使用成对列表:eg ),那么您可以将其转换为: 成对的元组。您已经在问题中做到了。需要A而不是因为结果依赖于元素的顺序和不变性。 冻结集。从数学的角度来看,这是一种更合适的方法,因为它只需要不可变元素上的 等式关系,而第一种方法除等式外还需要排

  • 是否有适当的方法来描述字典类型变量或在C#中留档注释的KeyValuePair。 像这样的,,

  • 由于我是Azure的新手,这个问题可能很傻。我正在尝试构建一个提供和管理虚拟机集群的服务。出于安全考虑,我不想在每个集群上放一些敏感数据。因此我决定为每个集群提供一个Azure密钥库来存储这些数据,并创建一个MSI(managed identity)并分派给集群的每个节点,这样vm就可以访问密钥库来获取机密。 在服务端,我需要提供vms、密钥库和MSI。将MSI分配给每个VM,同时授予MSI访问A

  • 我需要在C#中加密数据,以便将其传递给Java。Java代码属于第三方,但我得到了相关的源代码,因此我决定,由于Java使用Bouncy Castle库,所以我将使用C#端口。 解密工作正常。但是,解密仅在使用私钥使用encrypt时有效,而不是使用公钥。使用公钥时,解密失败,出现。 编辑: 我还添加了一个单元测试,它证明公钥等于从私钥中提取的公钥:

  • 我有一个非常大的不可变的密钥集,不适合存储在内存中,还有一个更大的引用列表,必须只扫描一次。如何在RAM中完成标记阶段?我确实有一个可能的解决方案,稍后我会写下来作为答案(不想破坏它),但也许还有其他我没有想到的解决方案。 我将试图重申这个问题,使其更“真实”: 你在Facebook工作,你的任务是找出哪些用户从未创建过带有表情符号的帖子。你所拥有的只是活动用户名列表(大约20亿),以及帖子列表(

  • 问题内容: 使用深度嵌套的python字典,我希望能够在这样的数据结构中分配值: 无需检查mydict [key]等实际上是否设置为dict,例如使用 附属词典的创建应即时进行。允许等效的最优雅的方法是什么-也许在标准上使用装饰器? 问题答案: class D(dict): def missing(self, key): self[key] = D() return self[key]