我的C#应用程序正在将文件中的图像缓存在RAM中,以便可以更快地(30-60 FPS)向用户显示。
它们被存储在Bitmap
个对象中。
大约200张图像后,它会抛出"System.OutOfMemoryException"
。
我尝试使用
System.Diagnostics.PerformanceCounter("Memory", "Available MBytes");
要查看上限并尝试将其保留在该上限之下,但它返回的值似乎无法准确匹配。
例如。如果我正常运行,它将以1,500 MB的可用空间开始,并引发300 MB左右的异常。
但是,如果我启动一个类似After Effects的大型应用程序,并使其占用大量内存,则该应用程序。
然后我的应用程序从300开始,处理大约200张图像,然后引发大约40 MB的异常,但是只有在它达到0 MB并由于某种原因弹回后才抛出该异常。
如何找出C#应用程序实际可使用的RAM数量,以便我知道可以缓存用于回放的确切图像数量,而又不会接近当前PC的上限和风险例外?
答案 0 :(得分:0)
简短答案:
使用GlobalMemoryStatusEx
Win32 API的ullAvailPageFile
更多详细信息:
System.Diagnostics.PerformanceCounter("Memory", "Available MBytes");
上面给出了“物理记忆”
这可以度量正在运行的进程可用的物理内存量(以兆字节为单位)。
您的计算机中始终有“虚拟内存”,并且很可能使用“页面文件”进行了配置
程序可以使用的适当度量是:Available Page File
https://msdn.microsoft.com/en-us/library/windows/desktop/aa366770(v=vs.85).aspx
ullAvailPageFile
当前进程可以提交的最大内存量(以字节为单位)。该值等于或小于系统范围内的可用提交值。
我找不到托管库调用来获取此信息。因此,可以使用pinvoke直接调用Win32 API的可用选项。
https://www.pinvoke.net/default.aspx/kernel32.GlobalMemoryStatusEx
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool GlobalMemoryStatusEx( [In, Out] MEMORYSTATUSEX lpBuffer);
在我的本地测试中,我发现如果“可用页面大小”小于1 GB,则该程序可能会随时因“内存不足”异常而开始失败。
请注意,该值不是固定值,它将随着您的程序/其他程序在系统中运行而改变。我的理解是,当您分配内存时,“页面文件”会增长(直到其配置的限制)。
您可能希望将应用程序构建为“ 64位”应用程序以使用更多的内存。
对于控制台应用程序,将其设置为“任何CPU”并清除“首选32位”复选框
页面文件设置
有关适当的页面文件大小的详细信息。在大多数情况下,它设置为可用RAM的倍数。
Windows 8.1和Windows Server 2012 R2
最大页面文件大小
3×RAM或4 GB,以较大者为准。