【问题标题】:How can I hold a list of string as efficiently (memory) as possible?如何尽可能有效地(内存)保存字符串列表?
【发布时间】:2019-02-08 07:57:40
【问题描述】:

我有一个巨大的字符串列表。我想将这些列表保持为内存高效。我试图保留一份清单。但是,它为每个包含 5 个字符的字符串使用 24 个字节。也就是说,应该有一些开销区域。

然后,我尝试保留一个字符串数组。内存使用效率有点高。但是,我仍然有内存使用问题。

如何保存字符串列表?我知道“C# 为每个字符保留 2 个字节”。我想保存一个包含 5 个字符的字符串,即 5*2 = 10 个字节。但是,为什么它在这个过程中使用 24 字节呢?

感谢您的帮助。

enter image description here

【问题讨论】:

  • 您忽略了对象开销,以及 C# 字符串“知道”其长度的事实。请参阅codeblog.jonskeet.uk/2011/04/05/of-memory-and-strings 了解有关这方面的大量详细信息。
  • 一个字符串也有长度,所以你至少有 n*2+4 个字节,其中 n 是长度。但问题是:你必须对字符串序列做什么?它是一个常数吗?它是文件的内容吗?你必须如何消费它?如果您知道要阅读什么以及如何搜索它,您甚至可以将它存储为一个字节数组。您真的需要将整个内容存储在内存中吗?
  • 请注意,如果您有很多相等的字符串,这将有助于 lot 确保每个不同的字符串值只有一个字符串对象。跨度>

标签: c# arrays list memory-management


【解决方案1】:

首先,请注意List<string>以正确的大小创建string[](大小相同)之间的差异对于任何重要的大小都是无关紧要的; List<T> 实际上只是 T[] 的精美包装器,具有插入/调整大小/等功能。如果您只需要保存数据:T[] 可以,但通常List<T> 也可以。

至于字符串 - 不是 C# 保留任何东西 - 是 .NET 定义 string 是一个对象,它在内部是一个长度 (int) 加上内存用于 char 数据,每个char 2 个字节。但是:.NET 中的对象具有对象标题、填充/对齐等 - 重要的是:最小尺寸。所以是的,它们占用的内存比您试图表示的原始数据更多。

如果您只需要实际数据,您或许可以不将数据存储为string,而是存储为原始内存——简单的大byte[]byte*,或者作为int[]/int*(用于页面中的长度和/或偏移量)和char[]/char*(用于实际字符数据)或byte[]/byte*(如果可以的话)的孪生对处理编码数据(即您主要对 IO 工作感兴趣)。但是,使用这样的表单会非常不方便 - 除非您在 string 中交谈,否则几乎没有常见的 API 愿意与您一起玩。 一些 API 可以接受原始字节/字符数据,但它们主要是编码器/解码器 API 和一些 IO API。再说一遍:除非那是你正在做的:结局不会很好。最近,出现了一些 Span<char> / Span<byte> API,这会使这稍微less 不方便(如果您可以使用最新的 .NET Core 构建等),但是:我强烈怀疑在在最常见的情况下,您只需要接受 string 开销并接受它。

【讨论】:

  • 我明白了,我会尝试这些方法。谢谢大家
  • List<T> 是使用动态数组实现的。所以内部是T[]
  • @Rahul 是的,我说过...“List<T> 实际上只是 T[] 的精美包装器,具有插入/调整大小/等功能”
  • 我知道“List 是使用动态数组实现的”。当我使用数组时,它有点内存效率。但是,我现在将尝试 byte[] 或 char[] 方法。我想,这会解决我的问题。
  • @Ufuk 正如 Marc 指出的那样,许多 API 都期望 string 输入,因此这取决于您需要对字符串做什么。例如。 Regex 不理解 Span 所以你必须创建字符串,因此在这种情况下无法真正解决开销。
【解决方案2】:

64 位 .NET 中任何对象的最小大小为 24 字节。

在 32 位中它有点小,但对象头总是至少有 8 个字节,在这里我们希望字符串存​​储它的 length(4 个字节)。 8 + 4 + 10 = 22。我猜它还希望/需要所有对象都是 4 字节对齐的。因此,如果您将它们存储为对象,您将不会获得更小的表示形式。

如果都是 7 位 ASCII 类型的字符,您可以将它们存储为字节数组,但每个数组仍然会占用一些空间。

您最好的方法(我很欣赏这一点更像是评论)是提出不同的处理算法,这些算法一开始就不需要它们都在内存中。

【讨论】:

  • OP 还可以有效地保留一个巨大的单个数组/字符串/任何东西,并保留一个偏移量列表。 (这些偏移量可以用值类型表示。)不过,我们需要更多关于上下文的信息才能知道最佳方法。
猜你喜欢
  • 2014-06-16
  • 1970-01-01
  • 2019-07-18
  • 2012-04-22
  • 1970-01-01
  • 1970-01-01
  • 2012-10-16
  • 2013-09-11
  • 1970-01-01
相关资源
最近更新 更多