【问题标题】:Alternative to Dictionary for lookup替代字典进行查找
【发布时间】:2012-05-24 17:29:47
【问题描述】:

我需要建立查找表。我使用 Dictionary 它包含 45M long 和 45M int 。只要 key 和 int 作为 value 。集合的大小为 (45M*12) 其中 long 为 8 字节,int 为 4 字节 大小约为 515 MB。但实际上进程的大小是 1.3 Gbyte 。该过程仅包含此查找表。 Mat be,有没有字典的替代品?

谢谢

【问题讨论】:

  • 进程大小为 1.3 GB:这不是问题。不要使用 TaskManager 来测量内存使用情况。
  • 进程的大小是否会导致问题?您是否遇到 OOM(内存不足)异常?
  • 这就是我们拥有数据库的原因。查资料!!
  • @banging 即使是内存数据库的查找时间也会比进程中的内存数据结构慢几个数量级。对于某些应用程序(例如资本市场交易),这可能是一个有意义的速度差异。并不是说这里就是这种情况,但在这些情况下,数据库并不总是答案。
  • 长键的值范围是否有任何限制,可以直接用作 int 值数组的索引?

标签: c# collections lookup-tables


【解决方案1】:

你愿意付出多少努力?
你可以使用

KeyValuePair<long,int>[] table = new KeyValuePair<long,int> [45 M];

然后在第一列 (long Key) 上对其进行排序,并使用二进制搜索来查找您的值。

【讨论】:

  • 对这个想法的改进是定义一个包含 long 和 int 的结构,然后将该结构创建一个数组。
  • @hatchet - 不是提高速度,但是会更整洁。元组只是让我写一个 1 行答案。
  • 没有考虑速度和空间一样多,因为使用元组,数组将是一个对象数组,然后您也将拥有对象本身的空间(long 和 int)。
  • @hatchet - 你完全正确,它应该是一个结构。将编辑。
  • @HenkHolterman- 我认为一个很好的解决方案,因为 OP 指定了一个不使用长键的大部分高位的范围,所以将您的方法与我的想法结合使用回答。让结构在内部将键表示为 int 和一个字节或一个 int 一个单词,并让结构实现自己的 GetHashCode(),并公开一个属性以获取设置长键(然后将其转换为内部表示有点摆弄)。
【解决方案2】:

您可以使用 SortedList 而不是 Dictionary,这将提高内存效率,但 CPU 效率可能略低,忽略有关测量内存的问题以及为什么首先需要一次性加载这么多数据 :)

【讨论】:

    【解决方案3】:

    字典有一个保存数据的底层数组,但数组的大小必须大于你拥有的项目数,这就是字典查找速度的来源。事实上,底层数组的大小应该比项目数(25+%)大很多。结合这一点,当您添加项目时,该底层数组正在被取消分配和重新创建(以使其更大),您可能有相当多的内存准备好进行垃圾收集(这意味着如果您实际上需要更多内存GC 会回收它,但既然你目前有足够的东西,它就不会打扰)。

    这个字典消耗的内存是否超出了您的允许范围,或者您只是好奇为什么它比您想象的要多?您可以使用其他选项(其他答案和 cmets 列出了一些),它们会使用更少的内存但也会更慢。您是否遇到内存不足的问题?

    【讨论】:

      【解决方案4】:

      如果您的范围被限制为 10^12 的最大 long 值,那么空间方面的问题是您必须使用 long,因为您只需要比 int 可以容纳的多几位。如果是这种情况,您可以执行以下操作: 将数据存储在 512 字典数组中

       var myData = new Dictionary<int,int>[512];
      

      要引用与 long 值关联的 int(在此示例中我将其称为“键”),您可以执行以下操作:

      myData[key & 511].Add((int) (key >> 9), intValue);
      int result = myData[(int) (key & 511)][(int) (key >> 9)];
      

      可能需要调整您创建的字典数量以及位摆弄中使用的位数以适应数据的真实约束。使用这种方法可以减少大约三分之一的内存使用量

      【讨论】:

        【解决方案5】:

        另一种方法,假设数据是静态的:使用两个排序数组 - 一个是 long 数组,一个是 int 数组。确保一个索引 N 处的项目是另一个索引 N 处的键的值。使用Array.BinarySearch 查找您要查找的键值。

        【讨论】:

          猜你喜欢
          • 2010-11-06
          • 2018-09-24
          • 1970-01-01
          • 2011-05-26
          • 2015-12-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多