算法计算不同类型的内存

时间:2016-04-22 18:39:23

标签: c#

我正在尝试计算内存。我使用以下代码计算了Available,InUse,Free和Cached

  ObjectQuery wql = new ObjectQuery("SELECT * FROM Win32_OperatingSystem");
            ManagementObjectSearcher searcher = new ManagementObjectSearcher(wql);
            ManagementObjectCollection results = searcher.Get();

            //total amount of free physical memory in bytes
            var Available = new ComputerInfo().AvailablePhysicalMemory;
            //total amount of physical memory in bytes
            var Total = new ComputerInfo().TotalPhysicalMemory;

            var PhysicalMemoryInUse = Total - Available;
            Object Free = new object();
            foreach (var result in results)
            {
                //Free amount
                Free = result["FreePhysicalMemory"];
            } 
            var Cached = Total - PhysicalMemoryInUse - UInt64.Parse(Free.ToString());

如何计算待机,硬件保留和修改内存,如Windows资源监视器中所示?

enter image description here

3 个答案:

答案 0 :(得分:7)

保留的硬件是物理安装内存量与操作系统报告的物理内存总量之间的差异。

性能计数器可以检索其他信息。我在下面有一个示例类,但是知道这不是一个强大的实现。您将要添加正确的错误处理和资源清理。但是,缓存此类的实例并在需要时通过Refresh()更新值应该可以很好地执行。

public sealed class MemoryInfo : IDisposable
{
    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool GetPhysicallyInstalledSystemMemory(out ulong memoryInKilobytes);

    private readonly PerformanceCounter availableCounter;
    private readonly PerformanceCounter modifiedCounter;
    private readonly PerformanceCounter freeCounter;
    private readonly PerformanceCounter standbyCoreCounter;
    private readonly PerformanceCounter standbyNormalCounter;
    private readonly PerformanceCounter standbyReserveCounter;

    private ulong osTotalMemory;

    public ulong ModifiedBytes { get; private set; }
    public ulong InUseBytes { get; private set; }
    public ulong StandbyBytes { get; private set; }
    public ulong FreeBytes { get; private set; }
    public ulong HardwareReserved { get; }

    public MemoryInfo()
    {
        var computerInfo = new ComputerInfo();

        osTotalMemory = computerInfo.TotalPhysicalMemory;

        ulong installedPhysicalMemInKb;
        GetPhysicallyInstalledSystemMemory(out installedPhysicalMemInKb);

        this.HardwareReserved = installedPhysicalMemInKb * 1024 - osTotalMemory;

        modifiedCounter = new PerformanceCounter("Memory", "Modified Page List Bytes");
        standbyCoreCounter = new PerformanceCounter("Memory", "Standby Cache Core Bytes");
        standbyNormalCounter = new PerformanceCounter("Memory", "Standby Cache Normal Priority Bytes");
        standbyReserveCounter = new PerformanceCounter("Memory", "Standby Cache Reserve Bytes");
        freeCounter = new PerformanceCounter("Memory", "Free & Zero Page List Bytes");
        availableCounter = new PerformanceCounter("Memory", "Available Bytes");

        Refresh();
    }

    public void Refresh()
    {
        ModifiedBytes = (ulong)modifiedCounter.NextSample().RawValue;
        StandbyBytes = (ulong)standbyCoreCounter.NextSample().RawValue +
                       (ulong)standbyNormalCounter.NextSample().RawValue +
                       (ulong)standbyReserveCounter.NextSample().RawValue;
        FreeBytes = (ulong)freeCounter.NextSample().RawValue;
        InUseBytes = osTotalMemory - (ulong) availableCounter.NextSample().RawValue;

    }

    public void Dispose()
    {
        modifiedCounter.Dispose();
        standbyCoreCounter.Dispose();
        standbyNormalCounter.Dispose();
        standbyReserveCounter.Dispose();
        freeCounter.Dispose();
        availableCounter.Dispose();
    }
}

这样做有一些缺点,比如性能计数器没有组合在一起,所以你不会得到一个真实的'特定时间点的系统内存快照。您可以使用PInvoke直接使用Pdh* win32 api函数来改进它。

您也可以将其更改为使用WMI(数据位于Win32_PerfRawData_PerfOS_Memory),但我不知道它将如何执行。

答案 1 :(得分:0)

查看您所在的内容是否在此处 - 创建一个控制台应用程序并将其粘贴到program.cs的内容上。从命令行运行它>到文件并查找相关的内存计数器。

using System;
using System.Diagnostics;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            var categories = PerformanceCounterCategory.GetCategories();

            foreach (var cat in categories)
            {
                if (cat.CategoryType != PerformanceCounterCategoryType.MultiInstance)
                {
                    Console.WriteLine("Category: " + cat.CategoryName);
                    foreach (var counter in cat.GetCounters())
                    {
                        Console.WriteLine("Counter: " + counter.CounterName + ": " + counter.NextSample().RawValue);
                    }
                }
                else //if (cat.CategoryType == PerformanceCounterCategoryType.MultiInstance)
                {
                    foreach (var instance in cat.GetInstanceNames())
                    {
                        Console.WriteLine("Instance: " + instance);
                        foreach (var counter in cat.GetCounters(instance))
                        {
                            try
                            {
                                Console.WriteLine("Counter: " + counter.CounterName + ": " + counter.NextSample().RawValue);
                            } catch
                            { 
                                // swallow exceptions for counter that require a set base. 
                            }
                        }
                    }
                }
            }

            Console.ReadLine();           
        }      
    }
}

答案 2 :(得分:0)

我使用了Christopher的示例并将其扩展为所有WMI以获得硬件保留。

using System;
using System.Management;

namespace ConsoleApplication2
{
    class Program
    {

        static void Main(string[] args)
        {
            try
            {
                ManagementScope Scope;
                Scope = new ManagementScope(String.Format("\\\\{0}\\root\\CIMV2", "."), null);
                Scope.Connect();

                double totalVisibleMemory = 0;

                ObjectQuery wql = new ObjectQuery("SELECT * FROM Win32_OperatingSystem");
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(wql);
                ManagementObjectCollection results = searcher.Get();

                foreach (ManagementObject result in results)
                {
                    totalVisibleMemory = double.Parse(result["TotalVisibleMemorySize"].ToString()) / 1024;
                    Console.WriteLine("Total Visible Memory: {0:0} mb", totalVisibleMemory);
                    Console.WriteLine("Free Physical Memory: {0:0} mb", double.Parse(result["FreePhysicalMemory"].ToString()) / 1024);
                    Console.WriteLine("Total Virtual Memory: {0:0} mb", double.Parse(result["TotalVirtualMemorySize"].ToString()) / 1024);
                    Console.WriteLine("Free Virtual Memory: {0:0} mb", double.Parse(result["FreeVirtualMemory"].ToString()) / 1024);
                }

                ObjectQuery Query = new ObjectQuery("SELECT Capacity FROM Win32_PhysicalMemory");
                ManagementObjectSearcher Searcher = new ManagementObjectSearcher(Scope, Query);
                UInt64 Capacity = 0;
                foreach (ManagementObject WmiObject in Searcher.Get())
                {
                    Capacity += (UInt64)WmiObject["Capacity"];
                }

                var totalPhysicalMemory = Capacity / (1024 * 1024); 
                Console.WriteLine(String.Format("Total Physical Memory {0:0} mb", Capacity / (1024 * 1024)));
                var hardwareReserved = totalPhysicalMemory - totalVisibleMemory;

                    Console.WriteLine(string.Format("Hardware Reserved Memory {0:0} mb", hardwareReserved));
            }
            catch (Exception e)
            {
                Console.WriteLine(string.Format("Exception {0} Trace {1}", e.Message, e.StackTrace));
            }
            Console.WriteLine("Press Enter to exit");
            Console.Read();
        }
    }
}