【问题标题】:C# Get used memory in %C# 以 % 为单位获取已用内存
【发布时间】:2012-04-19 02:50:47
【问题描述】:

我创建了一个性能计数器,可以检查总内存使用率(以 % 为单位),但问题是它给我的值与任务管理器中显示的值不同。例如:我的程序说 34%,但任务管理器说 40%。

有什么想法吗?

注意
我尝试获取系统的可用 RAM,而不是进程使用的 RAM。

当前代码

private PerformanceCounter performanceCounterRAM = new PerformanceCounter();

performanceCounterRAM.CounterName = "% Committed Bytes In Use";
performanceCounterRAM.CategoryName = "Memory";

progressBarRAM.Value = (int)(performanceCounterRAM.NextValue());
            labelRAM.Text = "RAM: " + progressBarRAM.Value.ToString(CultureInfo.InvariantCulture) + "%";

编辑
我用计时器每秒刷新一次进度条和标签。

【问题讨论】:

  • 与任务管理器相比,是不是TM和你的值只取决于时间延迟?我的意思是,TM 也会每秒刷新一次它的值。因此,如果您的应用程序和任务管理器具有同步的刷新时间,那么它们 那么 是否具有相同的值?
  • 我也试过了,但程序显示的值仍然低于 TM :(.
  • 正在使用哪个操作系统? XP、Win 7、Vista?

标签: c# performancecounter


【解决方案1】:

性能计数器不是个好主意。 使用此代码从任务管理器获取内存使用百分比

var wmiObject = new ManagementObjectSearcher("select * from Win32_OperatingSystem");

var memoryValues = wmiObject.Get().Cast<ManagementObject>().Select(mo => new {
    FreePhysicalMemory = Double.Parse(mo["FreePhysicalMemory"].ToString()),
    TotalVisibleMemorySize = Double.Parse(mo["TotalVisibleMemorySize"].ToString())
}).FirstOrDefault();

if (memoryValues != null) {
    var percent = ((memoryValues.TotalVisibleMemorySize - memoryValues.FreePhysicalMemory) / memoryValues.TotalVisibleMemorySize) * 100;
}

【讨论】:

  • 谢谢,这行得通。但是你可以对 cpu 使用百分比使用相同的值吗?
  • 查看stackoverflow.com/a/9778276/7656 获取通过ManagementObjectSearcher 获取CPU 使用率的示例
  • 您能解释一下为什么性能计数器不是一个好主意吗?
【解决方案2】:

您可以使用性能监视器底部的“显示说明”。 To quote

% Committed Bytes In Use 是 Memory\Committed Bytes 与 Memory\Commit Limit 的比率。承诺内存是物理内存 使用分页文件中保留的空间 需要写入磁盘。提交限制由大小决定 的分页文件。如果页面文件被放大,提交限制 增加,比例减少)。该计数器显示 仅当前百分比值;这不是平均水平。

是的,PM 使用分页文件,而 TM 使用实际 RAM。

【讨论】:

  • 请将您引用的来源添加到您的帖子中。
【解决方案3】:

您可以使用 GetPerformanceInfo windows API,它显示的值与 Windows 7 上的 Windows 任务管理器完全相同,这里是获取可用物理内存的控制台应用程序,您可以轻松获取 GetPerformanceInfo 返回的其他信息,请参阅 MSDN PERFORMANCE_INFORMATION结构文档看如何以 MiB 为单位计算值,基本上所有 SIZE_T 值都在页面中,所以你必须将它与 PageSize 相乘。

更新:我更新了这段代码以显示百分比,它不是最佳的,因为它调用了两次 GetPerformanceInfo,但我希望你明白这一点。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApplicationPlayground
{
  class Program
  {
    static void Main(string[] args)
    {
      while (true)
      {
        Int64 phav = PerformanceInfo.GetPhysicalAvailableMemoryInMiB();
        Int64 tot = PerformanceInfo.GetTotalMemoryInMiB();
        decimal percentFree = ((decimal)phav / (decimal)tot) * 100;
        decimal percentOccupied = 100 - percentFree;
        Console.WriteLine("Available Physical Memory (MiB) " + phav.ToString());
        Console.WriteLine("Total Memory (MiB) " + tot.ToString());
        Console.WriteLine("Free (%) " + percentFree.ToString());
        Console.WriteLine("Occupied (%) " + percentOccupied.ToString());
        Console.ReadLine();
      }
    }
  }

  public static class PerformanceInfo
  {
    [DllImport("psapi.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool GetPerformanceInfo([Out] out PerformanceInformation PerformanceInformation, [In] int Size);

    [StructLayout(LayoutKind.Sequential)]
    public struct PerformanceInformation
    {
      public int Size;
      public IntPtr CommitTotal;
      public IntPtr CommitLimit;
      public IntPtr CommitPeak;
      public IntPtr PhysicalTotal;
      public IntPtr PhysicalAvailable;
      public IntPtr SystemCache;
      public IntPtr KernelTotal;
      public IntPtr KernelPaged;
      public IntPtr KernelNonPaged;
      public IntPtr PageSize;
      public int HandlesCount;
      public int ProcessCount;
      public int ThreadCount;
    }

    public static Int64 GetPhysicalAvailableMemoryInMiB()
    {
        PerformanceInformation pi = new PerformanceInformation();
        if (GetPerformanceInfo(out pi, Marshal.SizeOf(pi)))
        {
          return Convert.ToInt64((pi.PhysicalAvailable.ToInt64() * pi.PageSize.ToInt64() / 1048576));
        }
        else
        {
          return -1;
        }

    }

    public static Int64 GetTotalMemoryInMiB()
    {
      PerformanceInformation pi = new PerformanceInformation();
      if (GetPerformanceInfo(out pi, Marshal.SizeOf(pi)))
      {
        return Convert.ToInt64((pi.PhysicalTotal.ToInt64() * pi.PageSize.ToInt64() / 1048576));
      }
      else
      {
        return -1;
      }

    }
  }
}

【讨论】:

  • 这似乎显示了可用内存量,这很好!但是我怎样才能得到百分比?我的意思是,我需要划分哪些值等?
  • 我整理了一个小类,现在用起来更方便了,这里是antoniob.com/…
  • 为什么您必须将物理可用和物理总数乘以页面文件大小?如果不这样做,我会得到像“7”和“2”这样没有意义的数字,但我觉得我想要不包含页面文件的实际内存大小。
  • 也许我没有正确理解你,但你必须乘以页面大小,因为 GetPerformanceInfo 方法返回页面中的值。
【解决方案4】:

我认为任务管理器报告的物理内存百分比实际上与您的 PerformanceCounter 使用的 % Committed Bytes In Use 不同。

在我的机器上,在性能监视器中查看时,这些值之间有 20% 的明显差异:

This article 表示 % Committed Bytes 指标考虑了页面文件的大小,而不仅仅是机器的物理内存。这可以解释为什么这个值总是低于任务管理器的值。

使用Memory \ Available Bytes 指标计算百分比可能会更好,但我不确定如何从 PerformanceCounter 获取物理内存总量。

【讨论】:

    猜你喜欢
    • 2011-11-30
    • 2018-12-01
    • 2017-05-17
    • 1970-01-01
    • 2012-11-07
    • 2011-04-30
    • 1970-01-01
    • 1970-01-01
    • 2016-04-08
    相关资源
    最近更新 更多