【问题标题】:Large memory blocks in a .NET app. What's optimal/recommended/scalable way to handle them?.NET 应用程序中的大内存块。处理它们的最佳/推荐/可扩展方式是什么?
【发布时间】:2012-04-20 12:10:44
【问题描述】:

想象一个通过组合和/或编辑其他文件来创建大文件的应用程序。 例如,一个应用程序:

  • 打开图像存档
  • 添加或替换部分图片
  • 更改现有图像的部分内容
  • 使用生成的图像集创建新存档

可以按任何顺序添加/替换/更改图像,因此直到执行结束才能创建新存档。

天真的方法是为原始存档中的每个图像创建一组MemoryStream 对象,然后在需要时更改/删除/替换流,然后将该组写入新存档。这种方法可能会在执行速度方面给出最好的结果。

问题很明显:并不总是有足够的内存来保存一组流。

在这种情况下你会推荐什么?

我想我应该用一些速度换取内存,并使用某种临时的非内存存储。不过,我不确定要使用什么。

我应该使用内存映射文件吗?还是带有某种创建和删除机制的普通旧临时文件?也许还有别的?

【问题讨论】:

  • 您对性能有什么要求吗?我很想去寻找普通的临时文件(可能存储在嵌套结构中以避免许多小文件变慢)并从那里开始。如果您隐藏在适当的界面后面,您以后随时可以改变主意!
  • 你考虑过使用微软的 Esent 吗? Wiki 页面:en.wikipedia.org/wiki/Extensible_Storage_Engine ESENT 托管 .Net 库:managedesent.codeplex.com
  • @JeffFoster 当然,我希望尽可能保持速度。除此之外,我没有特殊的性能要求。
  • @YS。我以前从未听说过。谢谢,我去看看。

标签: c# optimization memory-management large-files


【解决方案1】:

一种方法是使用文件和文件系统 - 大部分情况下 - 并提供某种内存缓存或映射。

如果您正在处理大量或相当大的文件 - 那么您无法真正将其与内存大小相匹配(或解压缩内存中的完整存档) - 除非我们谈论的是额外的硬件、RAM。

具体来说,我个人会选择...

class MemoryArchive {}  

...冒充你文件的前端,在后端存档。

您解压缩磁盘上的存档文件,临时文件夹 - 与大多数解压缩实用程序类似,然后处理“较小单位”的访问权限,即文件。

您的MemoryArchive 基本上表现得好像所有内容都在内存中,因此您需要有一些映射来代替内存流(或您决定用于直接访问对象级别的任何内容)到磁盘上的临时文件, 文件流。

可能还有一些强大的方法来处理同步 - 和/或错误、问题 - 因为您需要确保内存中的内容与磁盘上的内容同步 - 并保持“集成”完好无损。

到那时(取决于您的系统的性质等),主要任务可能是编写某种事务 - 围绕文件系统存储 - 这是您开始类似于数据库管理系统的地方。但那将是“规模的另一端”——如果你可以没有它生活,并保持简单,它可能不会有那么大的问题。

只是一个想法,尽管这完全取决于您的具体细节 -
即事物的规模(可能会有很大差异 - 即,如果内存允许在某些情况下您可以加载,并且处理速度足够快),存档中的“小变化”与存档的大小,更改的频率和性质.

在最简单的情况下,我几乎会将内容存储为临时文件并根据需要处理较小的增量更改。

并且拥有某种MemoryArchive 会给你一个围绕未来事物的围栏 - 所以你可以改变它,或者基于例如混合几种方法。档案的大小等。实际上,在这些情况下通常最好采用一些“混合方法”,因为在处理不同的文件、大小时,您几乎无法做出“一刀切”的解决方案。

希望这会有所帮助,

【讨论】:

    【解决方案2】:

    您可以使用FileStream,并以与MemoryStream 相同的方式使用它。它本质上将确定缓冲和所有这些的负担放在了操作系统上。操作系统确实最了解,并让驱动程序和硬件处理复杂的缓存和微调。只需编写易于理解的代码并配置文件,配置文件,配置文件。

    如果分析显示需要,您可能可以混合使用这两种类型的流以获得性能良好且看起来不错的东西。

    【讨论】:

    • 这基本上是普通的旧临时文件,对吧?我也会试试的。
    • @Bobrovsky 是的,差不多。基于您的分析结果的混合可能会为您提供最好的服务,并为您提供专门调整的结果。
    【解决方案3】:

    首先,请注意.net limitation with LOH,基本上对于 LOH 对象,内存不会进行碎片整理,因此如果您连续创建和处置大量大对象,您“很可能”会遇到“内存不足异常” “因为碎片化的内存孔可能无法给您足够大的连续内存空间(.net 4.5 及更高版本已对此进行了一定程度的优化,但问题仍然存在)。因此,要回答您的问题,很大程度上取决于您的机器的体系结构,如果它是具有大量 RAM 的 64 位,并且您知道您的文件将恰好适合 LOH 问题,请使用内存中的对象,否则为Michael 建议使用文件流,这必然会发生。

    【讨论】:

    • 感谢您对 LOH 限制的警告。我想我已经看到了这种限制的后果,但并不知道。
    【解决方案4】:

    我应该使用内存映射文件吗?

    这肯定是首先想到的。这种方法的唯一问题是文件大小是否最终会占用所有映射空间。

    【讨论】:

    • 我需要处理很多文件。甚至可能有数千人。谢谢你的警告,我会向谷歌询问映射空间限制。
    猜你喜欢
    • 2014-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-26
    • 2012-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多