测量过程内存使用量会产生极低(错误)的值

Roy*_* T. 3 c# performance .net-4.0

我有以下代码来启动和监控进程:

Process process = new Process();
process.StartInfo.FileName = "foo.exe";

long maxMemoryUsage = 0;

process.Start()

while(!process.HasExited)
{
    maxMemoryUsage = Math.Max(maxMemoryUsage, process.PrivateMemorySize64);
}
Run Code Online (Sandbox Code Playgroud)

使用此代码运行大型应用程序后,根据任务管理器在其峰值时使用328 MB(内存"私有工作集").maxMemoryUsage的值和process.PeakPagedMemorySize64的值是364544.根据MSDN,这个值应该被解释为字节,这意味着它有点超过300KB,距离预期值一千倍.另一个进程.Peak ...内存属性也报告极低的值(所有都在兆字节以下,除了PeakVirtualMemorySize64,这是4MB,我认为这是该字段的最小值).

我已经尝试启动不同的应用程序(基于C#和C++,我有源代码),我知道这些应用程序使用很少或很多内存,而且内存值总是非常接近这个过程中看到的值.显然我做错了.

所以我的问题是:如何衡量我从C#应用程序中生成的进程的最大内存使用量.(注意,只要我知道程序退出后它的值,我就不需要ealtime值了,我也不需要它超精确,因为我不在乎它是27.04MB还是30MB,但我如果它是30MB或100MB,请小心).

编辑:这是一个完全可重现的测试用例

class Program
{
    static void Main(string[] args)
    {
        Process process = new Process();
        process.StartInfo.FileName = @"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\devenv.exe";

        long maxMemoryUsage = 0;

        process.Start();

        while(!process.HasExited)
        {
            maxMemoryUsage = Math.Max(maxMemoryUsage, process.PagedMemorySize64);
        }

        Console.Out.WriteLine("Memory used: " + (maxMemoryUsage / 1024.0) / 1024.0 + "MB");

        Console.ReadLine();
    }
}
Run Code Online (Sandbox Code Playgroud)

根据任务管理器Visual Studio使用103MB.关闭Visual Studio后,程序报告0.3984375MB.

Sri*_*vel 5

进程类被高度缓存.除非你调用Refresh方法,否则你只会获得缓存结果,无论你读了多少次属性.您需要调用Process.Refresh来获取非缓存结果.

引用msdn

当Process组件与流程资源相关联时,将根据关联流程的状态立即填充Process的属性值.如果关联过程的信息随后发生更改,则这些更改不会反映在Process组件的缓存值中.Process组件是关联时进程资源的快照.要查看关联进程的当前值,请调用Refresh方法.

那么,您的代码将变为:

while(!process.HasExited)
{
    process.Refresh();
    maxMemoryUsage = Math.Max(maxMemoryUsage, process.PrivateMemorySize64);
}
Run Code Online (Sandbox Code Playgroud)

您也可以考虑查看process.PeakXXX属性,我认为这对您有所帮助.