【问题标题】:Which consumes less space, UInt64 or a string in C#哪个消耗更少的空间,UInt64 或 C# 中的字符串
【发布时间】:2012-03-03 10:38:18
【问题描述】:

在 C# 上下文中最好的想法是什么,

  1. 在 C# 中,我使用的是字典。我希望它使用更少的内存空间。什么会更好?

    键类型为Uint64 或键类型为string 的字典?在这两种情况下,值都是一个自定义类,每个字典都相同。

    我已将字典声明如下,

    private static readonly Dictionary<string, List<Node>> HashTable =
        new Dictionary<string, List<Node>>();
    

    类节点定义如下,

    public class Node
    {
        public UInt64 CurrentIndex { get; set; }
        public string NextHashedString { get; set; }
        public int NextHashPos { get; set; }
    }
    

    字符串的键实际上是一个字符串的哈希值,计算如下, 字符串的长度可以是 1 到 20 个字符。

    static UInt64 CalculateHash(string read, bool lowTolerance)
    {
        UInt64 hashedValue = 0;
        int i = 0;
        while (i < read.Length)
        {
            hashedValue += read.ElementAt(i) * (UInt64)Math.Pow(31, i);
            if (lowTolerance) i += 2;
            else i++;
        }
        return hashedValue;
    }
    

    现在,我想将此哈希值存储为字典的键。什么是最好的主意。我用作 Uint64 或将其转换为字符串并将字符串用作字典键。 我的主要目标是字典使用最少的空间并且搜索键的时间更快。

  2. 我有一个包含 3571079 个字符的文件。我可以将整个文件读入字符串还是需要高级数据结构?

【问题讨论】:

  • 您没有提供关于第一种情况的足够数据。能够在 UInt64 键或字符串键之间进行选择是不寻常的......
  • 这个问题我不清楚...你能提供一些你想要达到的目标的例子吗?
  • @JonSkeet 我用 sn-ps 修改了问题。
  • @digEmAll 请查看修改后的问题。
  • 好吧,你也可以更新问题标题,这对这种情况不是很有帮助。

标签: c# string data-structures dictionary uint64


【解决方案1】:

使用 UInt64 而不是字符串(或任何其他引用类型)作为字典的键实际上会消耗更少的内存。使用像字符串这样的引用类型需要字典在其内部数据结构中存储对键的引用,这将导致被引用的对象(字符串)也保存在内存中,包括每个对象的开销等。当键是 UInt64,(当前实现)字典存储键的值而不是对键的引用(作为泛型工作的正常方式的一部分),没有任何单独的键对象。

我能想到的只有一种情况,UInt64 键可能导致比字符串更高的内存使用量:如果进程是 32 位 (x86),则引用是 32 位的。如果字典很大,但几乎是空的,就会有很多空的Dictionary&lt;K,V&gt;.Entry 实例。对于 UInt64 键,这些实例的键部分将是 64 位(即使没有分配显式值),而对于字符串键,它只有 32 位。因此,对于具有 UInt64 键的字典,分配的内存总量将更多。但这是一个非常理论化的情况。

因此,如果您可以使用 UInt64 键而不是字符串而不牺牲软件设计的其他品质,那么使用它们就没有错。但是在真正需要之前不要开始优化。用 Donald Knuth 的话来说:“过早的优化是万恶之源”

更新:因为您更新了帖子以显示您的 UInt64 值是如何计算的:

  1. 如果您只是通过在 UInt64 值上调用 ToString 来派生字符串键,您应该首先选择 UInt64 版本。无论如何都会更有效率。

  2. 使用散列作为键可能有点棘手。您需要确保哈希不会发生冲突。您的哈希函数乍一看并不是特别好,但这当然取决于您的用例。但这超出了我想的这个问题的范围。

【讨论】:

  • 嗨,“如果字典很大,但几乎是空的,会有很多空的 Dictionary.Entry 实例”是什么意思,字典不会为空。因为每次我生成一个有效的键值对时,我都会将它添加到字典中。
  • @Pbasak 这更多是理论上的考虑,在实践中不会影响您。对于所有实际应用,UInt64 键将比字符串键消耗更少的内存。
  • 实际上是一个节点列表。从代码中可以看出。如果出现相同的哈希值,我会将这些节点添加到列表中。我知道我的哈希函数不是很好。我就此提出了一个单独的问题。
猜你喜欢
  • 2021-12-27
  • 2012-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-07
  • 2015-07-04
  • 1970-01-01
相关资源
最近更新 更多