我读到了内存限制
我有一个应用程序可以处理需要流式传输的巨大图像。就像在单帧视频处理中一样。该应用程序有大约40个插件,每个插件可以包含数据库,图像处理和WPF GUI。
该应用程序还有2个使用旧版DotNet Winforms的插件。
除了应用程序在RAM中超过大约1.2GB之外,一切正常。然后,在分配新内存的插件中的异常位置,我收到“Out of Memory exception”。
我正在编写一个编译为32位的64位系统。 我不知道该怎么做以及如何搜索任何错误。
是否有限制或我能抓住它们吗?
答案 0 :(得分:20)
编写一个消耗所有可用虚拟内存空间的32位程序非常困难。你的墙壁远远低于2千兆字节,你首先用完的是一大块虚拟内存,它足以满足要求的大小。您只能通过小额分配来获得最高2GB的限制,小到足以填入漏洞。
那个墙在一个操纵位图的程序中很早就命中了。他们可以消耗大量的VM来存储位图像素,它需要是一个连续的分配。它们存储在array
中,而不是tree
中。它是一种非托管内存分配,典型的.NET内存分析器往往无助于向您展示问题。
关于地址空间碎片,您无法做任何合理的事情,消耗所有可用虚拟机的概念应该是错误的。通过在post build event中运行editbin.exe
并使用其/LARGEADDRESSAWARE
命令行选项,可以在64位操作系统上获得更多的喘息空间。这允许进程使用可用的4千兆字节的VM,这是64位版本的Windows特有的选项,因为Windows不需要高2GB。当然,将平台目标更改为AnyCPU是获取虚拟内存的快捷方式。
答案 1 :(得分:0)
在Windows上运行的32Bit应用程序(即使操作系统是64位)也有4Gb地址空间,但这被分成2Gb应用程序/ 2Gb系统(可以使用不同的启动开关更改为3/1)。 / p>
您使用的总内存很可能实际上是2Gb而不是1.2Gb,您如何确定这个1.2Gb的数字,您是否使用process explorer工具查看了应用程序?
如果您将应用程序更改为ANYCPU或64位,您应该会发现64Bit OS上的此限制消失(很好地移动到更大的值)。
答案 2 :(得分:0)
为了更具确定性,您应该编写一些集成测试来检查内存最终的位置。您现在可以使用WMemoryProfiler执行此操作。我首先加载1500x1500大小的图像,清理所有内容,然后将所有对象标记为已知。然后我会重新拍摄大图像并检查分配了哪些新对象,并清楚地了解它们中有多少是谁以及谁拥有它们。
你说使用了很多外部模块。也许你应该放弃一些由于不明智的内存使用并用更好的东西替换它们。现在你可以检查一下。
如果达到极限,您仍然可以卸载一些图像并根据需要加载它们,如果您和您的插件支持惰性结构,例如IEnumerable<Image>
,您作为提供商可以决定何时加载图像以及多长时间将它保存在缓存中,直到你摆脱引用以帮助释放一些内存。
[Test]
public void InstanceTracking()
{
using (var dumper = new MemoryDumper()) // if you have problems use to see the debugger windows true,true))
{
TestWith1500x1500();
dumper.MarkCurrentObjects();
TestWith3000x3000();
ILookup<Type, object> newObjects = dumper.GetNewObjects()
.ToLookup( x => x.GetType() );
// here we do find out which objects are holding most of the memory
MemoryStatistics statOld = dumper.GetMemoryStatistics();
foreach (var typeInfo in statOld.ManagedHeapStats
.OrderByDescending(x => x.Value.Count))
{
Console.WriteLine("Type {0} has {1} instances of total size {2:N0} bytes",
typeInfo.Key,
typeInfo.Value.Count,
typeInfo.Value.TotalSize);
}
// then check with the info from above who is holding the most interesting new objects.
Console.WriteLine("New Strings:"); // just an example perhaps you should have a look at the images.
foreach (var newStr in newObjects[typeof(string)] )
{
Console.WriteLine("Str: {0}", newStr);
}
}
}