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