我已经创建了一个性能计数器,它可以检查%的总内存使用量,但问题是它没有给我与任务管理器显示的相同的值。例如:我的程序说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) + "%";
修改
我用计时器每秒刷新进度条和标签。
答案 0 :(得分:52)
你可以使用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;
}
}
}
}
答案 1 :(得分:8)
我认为任务管理器报告的物理内存百分比实际上是与PerformanceCounter使用的% Committed Bytes In Use
不同的指标。
在我的机器上,在性能监视器中查看时,这些值之间有20%的明显差异:
This article表示%Committed Bytes指标考虑了页面文件的大小,而不仅仅是机器的物理内存。这可以解释为什么这个值始终低于任务管理器的值。
使用Memory \ Available Bytes
指标计算百分比可能会更好,但我不确定如何从PerformanceCounter获取物理内存总量。
答案 2 :(得分:6)
性能计数器并不是一个好主意。 使用此代码从任务管理器中获取%的内存使用量
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;
}
答案 3 :(得分:0)
您可以使用性能监视器底部的“显示说明”。 To quote
使用中的承诺字节数百分比是内存\承诺字节数与内存\提交限制的比率。承诺的内存是物理内存 用于在页面文件中保留哪个空间 需要写入磁盘。提交限制由大小决定 页面文件。如果页面文件被放大,则提交限制 增加,比例减少)。此计数器显示 仅限当前百分比值;这不是一个平均值。
Soo是PM使用分页文件,而TM使用实际RAM。