Jinjinov / Hardware.Info

Battery, BIOS, CPU - processor, storage drive, keyboard, RAM - memory, monitor, motherboard, mouse, NIC - network adapter, printer, sound card - audio card, graphics card - video card. Hardware.Info is a .NET Standard 2.0 library and uses WMI on Windows, /dev, /proc, /sys on Linux and sysctl, system_profiler on macOS.
MIT License
492 stars 78 forks source link

Question: Obtaining CPU Utilization Metrics #64

Closed Kiryuumaru closed 1 month ago

Kiryuumaru commented 7 months ago

First off, big thanks for this awesome lib! I'm digging into CPU metrics on Windows and wondering how to get the PercentProcessorUtility instead of PercentProcessorTime. It seems more in line with Task Manager's display. Any tips on grabbing this specific metric?

Jinjinov commented 7 months ago

I am glad you like my lib :)

Take a look at GetCpuList https://github.com/Jinjinov/Hardware.Info/blob/master/Hardware.Info/Windows/HardwareInfoRetrieval.cs#L247 and replace PercentProcessorTime with PercentProcessorUtility like so:

    ulong percentProcessorUtility = 0ul;

    string queryString = "SELECT Name, PercentProcessorUtility FROM Win32_PerfFormattedData_PerfOS_Processor WHERE Name != '_Total'";
    ManagementObjectSearcher percentProcessorUtilityMOS = new ManagementObjectSearcher(_managementScope, queryString, _enumerationOptions);

    queryString = "SELECT PercentProcessorUtility FROM Win32_PerfFormattedData_PerfOS_Processor WHERE Name = '_Total'";
    ManagementObjectSearcher totalPercentProcessorUtilityMOS = new ManagementObjectSearcher(_managementScope, queryString, _enumerationOptions);

    try
    {
        foreach (ManagementBaseObject mo in percentProcessorUtilityMOS.Get())
        {
            // for each core:
            //Name = GetPropertyString(mo["Name"])
            //PercentProcessorUtility = GetPropertyValue<ulong>(mo["PercentProcessorUtility"])
        }

        foreach (ManagementBaseObject mo in totalPercentProcessorUtilityMOS.Get())
        {
            // total:
            percentProcessorUtility = GetPropertyValue<ulong>(mo["PercentProcessorUtility"]);
        }
    }
    catch (ManagementException)
    {
        // https://github.com/Jinjinov/Hardware.Info/issues/30
    }
    finally
    {
        percentProcessorUtilityMOS.Dispose();

        totalPercentProcessorUtilityMOS.Dispose();
    }
Kiryuumaru commented 7 months ago

Thank you for providing the solution! I've successfully implemented the usage of PercentProcessorUtility on Windows and it's working. I was wondering if there's a possibility to include support for this feature directly into the library in future updates? It would be really beneficial for users who rely on obtaining CPU utilization metrics

Jinjinov commented 7 months ago

I just noticed that I am using PercentProcessorTime under Win32_PerfFormattedData_PerfOS_Processor but PercentProcessorUtility is listed only under Win32_PerfRawData_Counters_ProcessorInformation

Googling "PercentProcessorUtility Win32_PerfFormattedData_PerfOS_Processor" actually returns no results.

As you can see here https://github.com/Jinjinov/Hardware.Info?tab=readme-ov-file#known-issues the main problem with these counters is their slow initialization.

If PercentProcessorUtility was under Win32_PerfFormattedData_PerfOS_Processor I would have no problem adding it into the lib. But querying another counter Win32_PerfRawData_Counters_ProcessorInformation might slow things down. I would have to test it extensively before adding it.

How large is the actual difference between PercentProcessorUtility and PercentProcessorTime values?

Kiryuumaru commented 7 months ago

Thanks for looking into it! From my real-time comparisons, I've noticed a pretty big gap between PercentProcessorUtility and PercentProcessorTime in real-time comparisons. During stress tests, PercentProcessorUtility seems to track Task Manager's numbers better, but it doesn't cap at 100% like Task Manager does—it goes beyond, hitting around 200%. As for Linux ubuntu, its PercentProcessorTime lines up pretty well with its system monitor, unlike Windows's PercentProcessorTime with Task Manager.

Jinjinov commented 7 months ago

Could you tell me a few startup times of your app under different conditions?

If you start the stopwatch in the first line of void Main() and immediately execute these, how long do they take

If you tell me these times for both DEBUG and RELEASE (or at least RELEASE) it would really help me a lot.

It would allow me to compare the startup times on your PC with those on my PC.

If I am going to query another counter Win32_PerfRawData_Counters_ProcessorInformation then I really want to test the impact on app startup time on as many PCs as possible.

ozkanpakdil-redgate commented 3 weeks ago

@Jinjinov When I look at learn microsoft site, I can not find any documentation about Win32_PerfRawData_Counters_ProcessorInformation do you know why ? Is WMI not liked by MS any more 😊

Jinjinov commented 3 weeks ago

I also don't know why Microsoft has no documentation for Win32_PerfRawData_Counters_ProcessorInformation.