Алгоритм расчета различных типов памяти

Я пытаюсь вычислить память. Я вычислил Доступные, 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());

Как я могу вычислить резервную, аппаратную резервную и измененную память, как показано в "Мониторе ресурсов" в окнах?

введите описание изображения здесь

Ответ 1

Аппаратное обеспечение - это разница между объемом физически установленной памяти и общим объемом физической памяти, сообщенной ОС.

Другая информация может быть получена счетчиками производительности. У меня есть примерный класс ниже, но знайте, что это не надежная реализация. Вы захотите добавить правильную обработку ошибок и очистку ресурсов. Однако кэширование экземпляра этого класса и обновление значений через 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();
    }
}

Есть минусы, чтобы сделать это таким образом, например, счетчики perf не сгруппированы вместе, поэтому вы не получите "реального" моментального снимка системной памяти в определенный момент времени. Вероятно, вы можете улучшить это, используя PInvoke для непосредственного использования функций Pdh* win32 api.

Вы также можете изменить его для использования WMI (данные находятся в Win32_PerfRawData_PerfOS_Memory), но я не знаю, как это будет выполняться.

Ответ 2

Посмотрите, что вы здесь, - создайте консольное приложение и вставьте его поверх содержимого 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();           
        }      
    }
}

Ответ 3

Я использовал образец Christopher и расширил его, чтобы все WMI получили Hardware Reserved.

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();
        }
    }
}