Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Algorithm To Calculate Different Types Of Memory

Tags:

c#

I am trying to calculate memory. I have calculated Available, InUse, Free, and Cached with the following code

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

How can I calculate Standby, Hardware Reserved, and Modified memory as shown in Resource Monitor in windows?

enter image description here

like image 546
nlstack01 Avatar asked Apr 22 '16 18:04

nlstack01


1 Answers

Hardware reserved is the difference between the amount of physically installed memory and the total amount of physical memory reported by the OS.

The other information can be retrieved by performance counters. I have an example class below, but know that this isn't a robust implementation. You'll want to add proper error handling and resource cleanup. However, caching an instance of this class and updating the values via Refresh() whenever you need it should perform fairly well.

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

There are downsides to doing it this way, like the perf counters are not grouped together, so you don't get a 'real' snapshot of the system memory at a specific point in time. You can probably improve that using PInvoke to use the Pdh* win32 api functions directly.

You could also change it to use WMI (data is in Win32_PerfRawData_PerfOS_Memory) but I don't know how it would perform.

like image 68
Christopher Currens Avatar answered Sep 20 '22 02:09

Christopher Currens