.NET应用程序中的大内存块。处理它们的最佳/推荐/可扩展方式是什么?

时间:2012-04-20 12:10:45

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

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

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

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

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

问题很明显:没有足够的内存来保存这组流。

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

我想我应该换一些内存速度并使用某种临时的内存存储。不过我不知道该怎么用。

我应该使用内存映射文件吗?还是普通的旧临时文件,有一些创建和删除它们的机制?也许别的什么?

4 个答案:

答案 0 :(得分:2)

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

如果分析显示需要,你可以混合两种类型的流来获得表现良好且看起来不错的东西。

答案 1 :(得分:2)

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

如果您正在处理大量或相当大的文件 - 那么您无法将其与内存大小完全匹配(或将内存中的完整存档解包) - 除非我们说的是额外的h / w,RAM。

具体来说,我个人会喜欢......

class MemoryArchive {}  

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

您将存档解压缩到磁盘,临时文件文件夹中 - 与大多数解压缩工具类似,然后处理'较小单元'的访问,即文件。

你的MemoryArchive基本上就像所有内存一样,所以你需要用一些映射代替内存流(或者你决定用于对象级别直接访问的任何内容)到临时文件中磁盘,文件流。

可能还有一些处理同步的强大方法 - 和/或错误,问题 - 因为您需要确保内存中的内容与磁盘上的内容同步 - 并保持'集成'不变。

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

只是一个想法,虽然这完全取决于你的具体细节 -
即事物的规模(可能变化很大 - 即如果内存允许在某些情况下你可以加载,如果处理足够快),档案中的“小变化”与档案的大小,变化的频率和性质如何。

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

拥有某种MemoryArchive可以让你围绕未来的事情 - 所以你可以改变它,或者根据例如实际上,在这些场景中,一些“混合方法”通常是最好的,因为在处理不同的文件,大小时,你很难做出“一刀切”的解决方案。

希望这有帮助,

答案 2 :(得分:2)

首先,请注意.net limitation with LOH,基本上使用LOH对象,内存不会进行碎片整理,所以如果你连续创建和处理很多大对象,你“很可能”“脱离”内存异常“因为碎片化的内存空洞可能无法为您提供足够大的连续内存空间(.net 4.5及以上版本已在一定程度上对此进行了优化,但问题仍然存在)。所以要回答你的问题,很大程度上取决于你的盒子的体系结构,如果它是一个有大量RAM的64位你知道你的文件适合LOH问题,请使用内存中的对象,否则作为迈克尔建议采用文件流进行颠簸必然会发生。

答案 3 :(得分:1)

  

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

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