【问题标题】:C# out of memoryC# 内存不足
【发布时间】:2020-12-23 03:34:01
【问题描述】:

这是 C# 代码:

string file = File.ReadAllText(@"C:\repos\BigTextSearch\Codes.txt");

我正在尝试在 .Net core C# 的内存中加载一个 10GB 的文件。我的 PC 中有 32GB RAM,其中 20GB 是免费的。 Codes.txt 包含大约十亿个代码。我不想根据我的问题分块。

当我运行控制台应用程序时,我收到“内存不足”错误。有没有办法增加堆大小?显然,根据一些答案,该进程允许的内存分配约为 3GB。我想知道是否可以增加它,以便我可以在内存中加载我的 10GB 文件。

【问题讨论】:

  • 这能回答你的问题吗? C# Increase Heap Size - Is It Possible
  • 你编译的是 32 位还是 64 位的应用程序?
  • 我正在编译 64 位
  • 你想用那个文件做什么?这对于为您提供一些解决方法至关重要。例如,如果您需要处理这些数据(搜索、修改、重写),也许将文件逐行加载到数据库系统中可能会为进一步处理提供一些优势
  • 你确定它是 64 位的吗?你检查EXE了吗? “首选 32 位” 复选框未在您的项目属性中设置?你用那个 10 gig 的字符串做什么?将其流式传输并以块的形式执行您所做的任何事情不是更有意义吗?

标签: c# memory operating-system heap-memory


【解决方案1】:

因此,C# 似乎每个字符使用 2 个字节 https://social.msdn.microsoft.com/Forums/vstudio/en-US/053aa028-774c-4a81-9586-16cb0e469177/how-to-know-the-byte-size-of-a-string?forum=csharpgeneral,这可以解释为什么 20GB 的空闲空间不足以容纳 10GB 的文件。我认为这是必须的,因为它被读取为 Unicode。

也许 .NET 默认使用 UTF-16 之类的东西

编辑

是的,它是 UTF-16 https://docs.microsoft.com/en-us/dotnet/api/system.char?view=netcore-3.1

【讨论】:

  • 谢谢。我明白了,你说得有道理。但是,根据 Michael 的建议,我尝试加载 2.25 GB GB 文件并遇到同样的内存不足问题。我尝试了 1.6 GB 文件并遇到了同样的问题。不过,我能够成功加载 900 MB 文件。实际上,确切地说,我有超过 21.8 GB 的可用内存。似乎我需要帮助的操作系统有一些限制。
  • 哎呀刚刚看到那个评论,嗯...当您加载 900MB 文件时,您的进程使用了​​多少内存?也许在内存使用量激增的地方发生了一些奇怪的事情,否则可能是一些奇怪的 OS / .NET 设置,我不确定。您可以尝试流式传输文件,但我认为另一条评论提到了
  • 此外,就您而言,当我加载像 600MB 这样的较小文件并使用以下代码加载字节数时,控制台上打印的字节数与文件大小匹配磁盘:字符串文件 = File.ReadAllText(@"C:\repos\BigTextSearch\words.txt"); Console.WriteLine(ASCIIEncoding.ASCII.GetByteCount(file));
  • 任务管理器/htop 说您的内存使用情况是当您加载其中一个文件时,它应该是文件大小的两倍左右。但我认为你是对的,这可能是一些限制它的设置
  • 或者可能是,即使我有 21 gig 可用内存,也没有足够的连续内存导致问题,只是大声思考。字符串需要连续的内存。
【解决方案2】:

场景 1: 在磁盘上,char 以 ASCII 格式存储,txt 文件中每个字符 1 个字节。在内存中,C# char 存储为 unicode,每个字符 2 个字节。话虽如此,如果您使用 C# 从磁盘加载 Y MB 文本文件,它将占用超过 2*Y MB 的内存或两倍以上。因此,请确保您有足够的内存可供使用。 (但这不是我的情况)

场景 2: 此外,您可能有足够的内存但没有足够的连续内存。例如,您可能有 20 GB 可用内存,但可能只有 1 GB 可用作单个块。记忆是碎片化的。 在这种情况下,如果您尝试创建大于 1 GB 的字符串或字符数组,您将“内存不足”。 (这是我的情况)

解决方案:

  1. 如果您真的想在内存中工作,请以块或逐行加载文件并将块存储在链表等数据结构中,以避免分配连续块。链表或类似的数据结构将分配分布式但链接的内存。 String、List、Dictionary、HashSet 等数据结构分配完全和/或部分连续的块,因此请避免使用它们。
  2. 取决于问题,但如果您的问题允许,请将文件流式传输到数据库中以进行进一步处理、搜索、更新、删除等。除非您使用完全内存,否则您将不得不处理一些 IO 延迟数据库。

【讨论】:

猜你喜欢
  • 2021-05-14
  • 1970-01-01
  • 2018-12-10
  • 2012-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多