如何找出实际可用于我的应用程序的内存量?

时间:2018-08-06 16:05:09

标签: c# memory garbage-collection malloc ram

我的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的上限和风险例外?

1 个答案:

答案 0 :(得分:0)

简短答案: 使用GlobalMemoryStatusEx Win32 API的ullAvailPageFile

更多详细信息:

System.Diagnostics.PerformanceCounter("Memory", "Available MBytes");

上面给出了“物理记忆”

https://blogs.msdn.microsoft.com/faber/2014/11/20/tracking-windows-performance-counters-by-application/

  

这可以度量正在运行的进程可用的物理内存量(以兆字节为单位)。

您的计算机中始终有“虚拟内存”,并且很可能使用“页面文件”进行了配置

程序可以使用的适当度量是: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位”应用程序以使用更多的内存。

  1. http://blogs.microsoft.co.il/sasha/2012/04/04/what-anycpu-really-means-as-of-net-45-and-visual-studio-11/
  2. .net console app 32 vs 64 bit

对于控制台应用程序,将其设置为“任何CPU”并清除“首选32位”复选框

页面文件设置

有关适当的页面文件大小的详细信息。在大多数情况下,它设置为可用RAM的倍数。

https://support.microsoft.com/en-in/help/2860880/how-to-determine-the-appropriate-page-file-size-for-64-bit-versions-of

  

Windows 8.1和Windows Server 2012 R2

     

最大页面文件大小

     

3×RAM或4 GB,以较大者为准。