Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

PDH query for counter "\Processor(0)\% Processor Time" always returns 99

Posted on 2008-06-13
6
Medium Priority
?
2,287 Views
Last Modified: 2013-12-10
I am trying to use the PDH library to retreive the CPU load for each CPU on a multi-processor PC but the query always returns 99.  It does not matter what processor I query for, even non-existent processors return 99.
HQUERY hQuery;
HCOUNTER hCounterCPU0, hCounterCPU1, hCounterCPU2;
PDH_FMT_COUNTERVALUE ppdhValue0, ppdhValue1, ppdhValue2;
long lCPU0Util, lCPU1Util, lCPU2Util;
 
wchar_t* szProcess0Time = _T("\\Processor(0)\\% Processor Time");
wchar_t* szProcess1Time = _T("\\Processor(1)\\% Processor Time");
wchar_t* szProcess2Time = _T("\\Processor(1000)\\% Processor Time");
 
if (PdhOpenQuery(NULL, 1, &hQuery) != ERROR_SUCCESS)
{
   ASSERT(false);
   return;
}
 
if ((PdhAddCounter(hQuery, szProcess0Time, NULL, &hCounterCPU0) !=
     ERROR_SUCCESS) ||
    (PdhAddCounter(hQuery, szProcess0Time, NULL, &hCounterCPU1) !=  
     ERROR_SUCCESS) ||
    (PdhAddCounter(hQuery, szProcess1Time, NULL, &hCounterCPU2) != 
    ERROR_SUCCESS))
{
   ASSERT(false);
   return;
}
 
if (PdhCollectQueryData(hQuery) != ERROR_SUCCESS)
{
   ASSERT(false);
   return;
}
 
lCPU0Util = 0;
lCPU1Util = 0;
lCPU2Util = 0;
 
if (PdhGetFormattedCounterValue(hCounterCPU0, 
                                PDH_FMT_LONG, NULL, 
                                &ppdhValue0) == ERROR_SUCCESS)
{
   lCPU0Util = ppdhValue0.longValue;
}
 
if (PdhGetFormattedCounterValue(hCounterCPU1, 
                                PDH_FMT_LONG, NULL, 
                                &ppdhValue1) == ERROR_SUCCESS)
{
   lCPU1Util = ppdhValue1.longValue;
}
 
if (PdhGetFormattedCounterValue(hCounterCPU2, 
                                PDH_FMT_LONG, NULL, 
                                &ppdhValue2) == ERROR_SUCCESS)
{
   lCPU2Util = ppdhValue2.longValue;
}

Open in new window

0
Comment
Question by:Eigel
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
6 Comments
 
LVL 13

Accepted Solution

by:
josgood earned 1200 total points
ID: 21783454
Issue an initial
   PdhCollectQueryData(hQuery);
and just throw it away.  Then sleep briefly, such as
   ::Sleep(1000);
and then issue the
   PdhCollectQueryData(hQuery);
that you really care about.

PDH often requires two snapshots in order to create valid data, and that seems to be true on my Core Duo.

I suggest writing a loop to check this, since the actual CPU usage may round down to zero in any one second.  Writing the values several times to sd::cout will show what you're getting.  You might also start some other process while running this test, so you can see some actual CPU time being consumed.

The test loop might look something like
   PdhCollectQueryData(hQuery);
   for (int i = 0; i < 25; i++) {
      ::Sleep(1000);
      if (PdhCollectQueryData(hQuery) != ERROR_SUCCESS) {
      ...your code here
   }
0
 

Author Comment

by:Eigel
ID: 21795151
josgood,  thanks for the Sleep()/re-query idea - that did in fact help but did not completely solve my problem.  Let me give you some more details about the test that I am running.  I am running the test PC on a network with a very high traffic load, around 900Mbps.  When I run the task manager performance monitor (with no applications running) I see one core (obviously running the NIC driver) running at 25%-35% of its utilization while the other core hangs out around 0%.  The overall CPU usage is reported as anywhere from 12% to 18%, clearly the average of the two cores.  After I added your Sleep() and re-query, I now get the overall CPU usage (i.e., something between 12% and 18%, and exactly the same value reported for both processors for each query) but not the individual core values that I can see on the graph.  Any ideas on how to get those individual core utilization values?  Thanks in advance, Vickie.
0
 
LVL 13

Assisted Solution

by:josgood
josgood earned 1200 total points
ID: 21803046
I'm sorry, but I don't have an answer.  I spent over an hour on this last night, but came up dry.

I wrote a quick application, using the PdhBrowseCounters API to see what counters are available on my core Duo with WinXP.  I didn't find anything applicable other than ProcessorTime -- nothing for cores or logical processors.  I think your Processor(0), etc. must be the way to do it.

Yet I get the same results as you and am currently baffled.

Do anyone at work have an MSDN subscription?  Could you open an incident with Microsoft technical support (costs money)?

That's all I have at the moment.
0
 

Author Comment

by:Eigel
ID: 21901103
Here is the code that I got from Microsoft Technical Support (for $99) that works correctly.
// GetPerformanceCounter.cpp : Defines the entry point for the console application.
//
 
#include "stdafx.h"
#include <windows.h>
#include <pdh.h>
#include <stdio.h>
 
BOOL WINAPI GetCounterValues(LPTSTR serverName);
 
void main(int argc, char *argv[])
{
    //if (argc > 1)
    //{
        // argv[1] - Server Name
 
        GetCounterValues(".");
 
}
 
BOOL WINAPI GetCounterValues(LPTSTR serverName)
{
    PDH_STATUS s;
 
    HQUERY hQuery;
 
    // Array to specify the performance object, counter and instance for
    // which performance data should be collected.
 
    // typedef struct _PDH_COUNTER_PATH_ELEMENTS {
    //   LPTSTR  szMachineName;
    //   LPTSTR  szObjectName;
    //   LPTSTR  szInstanceName;
    //   LPTSTR  szParentInstance;
    //   DWORD   dwInstanceIndex;
    //   LPTSTR  szCounterName;
    // } PDH_COUNTER_PATH_ELEMENTS, *PPDH_COUNTER_PATH_ELEMENTS;
 
    // Each element in the array is a PDH_COUNTER_PATH_ELEMENTS structure.
    PDH_COUNTER_PATH_ELEMENTS cpe[] =
    {
        { NULL, "Processor", "0", NULL, -1, "% Processor Time" },
        { NULL, "Processor", "1", NULL, -1, "% Processor Time" },
        { NULL, "Processor", "_Total", NULL, -1, "% Processor Time" }
    };
 
    HCOUNTER hCounter[sizeof(cpe)/sizeof(cpe[0])];
 
    char szFullPath[MAX_PATH];
    DWORD cbPathSize;
    int   i, j;
 
    BOOL  ret = FALSE;
 
    PDH_FMT_COUNTERVALUE counterValue;
 
    // Only do this setup once.
    if ((s = PdhOpenQuery(NULL, 0, &hQuery)) != ERROR_SUCCESS)
    {
        fprintf(stderr, "POQ failed %08x\n", s);
        return ret;
    }
 
    for (i = 0; i < sizeof(hCounter)/sizeof(hCounter[0]); i++)
    {
        cbPathSize = sizeof(szFullPath);
 
        cpe[i].szMachineName = serverName;
 
        if ((s = PdhMakeCounterPath(&cpe[i],
            szFullPath, &cbPathSize, 0)) != ERROR_SUCCESS)
        {
            fprintf(stderr,"MCP failed %08x\n", s);
            return ret;
        }
 
        if (cpe[i].szInstanceName)
        {
            printf("Adding [%s\\%s\\%s]\n",
                    cpe[i].szObjectName,
                    cpe[i].szCounterName,
                    cpe[i].szInstanceName);
        }
        else
            printf("Adding [%s\\%s]\n",
                    cpe[i].szObjectName,
                    cpe[i].szCounterName);
 
        if ((s = PdhAddCounter(hQuery, szFullPath, 0, &hCounter[i]))
            != ERROR_SUCCESS)
        {
            fprintf(stderr, "PAC failed %08x\n", s);
            return ret;
        }
    }
 
    for (i = 0; i < 20; i++)
    {
        Sleep(100);
 
        // Collect data as often as you need to.
        if ((s = PdhCollectQueryData(hQuery)) != ERROR_SUCCESS)
        {
            fprintf(stderr, "PCQD failed %08x\n", s);
            return ret;
        }
 
        if (i == 0) continue;
 
        // Extract the calculated performance counter value for each counter or
        // instance.
        for (j = 0; j < sizeof(hCounter)/sizeof(hCounter[0]); j++)
        {
            if ((s = PdhGetFormattedCounterValue(hCounter[j], PDH_FMT_DOUBLE,
                NULL, &counterValue)) != ERROR_SUCCESS)
            {
                fprintf(stderr, "PGFCV failed %08x\n", s);
                continue;
            }
            if (cpe[j].szInstanceName)
            {
                printf("%s\\%s\\%s\t\t : [%3.3f]\n",
                    cpe[j].szObjectName,
                    cpe[j].szCounterName,
                    cpe[j].szInstanceName,
                    counterValue.doubleValue);
            }
            else
                printf("%s\\%s\t\t : [%3.3f]\n",
                    cpe[j].szObjectName,
                    cpe[j].szCounterName,
                    counterValue.doubleValue);
        }
    }
 
    // Remove all the counters from the query.
    for (i = 0; i < sizeof(hCounter)/sizeof(hCounter[0]); i++)
    {
        PdhRemoveCounter(hCounter[i]);
    }
 
    // Only do this cleanup once.
    PdhCloseQuery(hQuery);
 
    return TRUE;
}

Open in new window

0
 
LVL 13

Assisted Solution

by:josgood
josgood earned 1200 total points
ID: 21904699
I believe I should get credit for answering the original question.  The Asker acknowledged that my answer helped and I believe it was complete for the original question.

I concede I did not have an answer for the follow-up question.
0

Featured Post

What Is Blockchain Technology?

Blockchain is a technology that underpins the success of Bitcoin and other digital currencies, but it has uses far beyond finance. Learn how blockchain works and why it is proving disruptive to other areas of IT.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
For both online and offline retail, the cross-channel business is the most recent pattern in the B2C trade space.
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

715 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question