UInt64或C#中的字符串占用的空间较小

本文关键字:空间 字符串 UInt64 | 更新日期: 2023-09-27 18:26:27

在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或C#中的字符串占用的空间较小

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

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

因此,如果您可以使用UInt64键而不是字符串,而不牺牲软件设计的其他质量,那么使用它们没有错。但在真正必要之前不要开始优化。用唐纳德·克努思的话来说:"过早优化是万恶之源"

更新:当你更新了你的帖子,显示你的UInt64值是如何计算的:

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

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