2

I am trying to code task manager and i stuck with %CPU for each process dy PID. I wrote something like, that:

  static float CalculateCPULoad(unsigned long long idleTicks, unsigned long long totalTicks)
{
    static unsigned long long _previousTotalTicks = 0;
    static unsigned long long _previousIdleTicks = 0;

    unsigned long long totalTicksSinceLastTime = totalTicks - _previousTotalTicks;
    unsigned long long idleTicksSinceLastTime = idleTicks - _previousIdleTicks;

    float ret = 1.0f - ((totalTicksSinceLastTime > 0) ? ((float)idleTicksSinceLastTime) / totalTicksSinceLastTime : 0);

    _previousTotalTicks = totalTicks;
    _previousIdleTicks = idleTicks;
    return ret;
}

static unsigned long long FileTimeToInt64(const FILETIME& ft) { return (((unsigned long long)(ft.dwHighDateTime)) << 32) | ((unsigned long long)ft.dwLowDateTime); }

And was using it like:

 hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hProcessSnap == INVALID_HANDLE_VALUE)
    {
        printError("Failed to create Process Snap");
        return FALSE;
    }
    pe.dwSize = sizeof(PROCESSENTRY32);

    if (!Process32First(hProcessSnap, &pe))
    {
        printError("Failed to move along process snap");
        CloseHandle(hProcessSnap);
        return FALSE;
    }

    do
    {
        printf("\n\n=====================================================");
        _tprintf(TEXT("\n PROCESS NAME: %s"), pe.szExeFile);
        printf("\n-----------------------------------------------------");
        dwPriorityClass = 0;
        hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID);
        if (hProcess == NULL)
        {
            printError("Failed to open process");
        }
        else
        {
            for (int i = 0; i < 2; i++)
            {
            GetProcessTimes(hProcess, &exist, &exit, &lastKernel, &lastUser);
            GetSystemTimes(&lastIdle, 0, 0);
            GetCPULoad(lastIdle, lastKernel, lastUser);
            Sleep(2500);
            }
        std::cout << GetCPULoad(lastIdle, lastKernel, lastUser) << "\n";
        CloseHandle(hProcess);
        }
    } while (Process32Next(hProcessSnap, &pe));
    CloseHandle(hProcessSnap);
    return (TRUE);
}

I know that using sleep() here isnt a good idea,but i havent think up anything better for now.

Pls help me with some code examples,if you can.

Also i want to know am i right that:

CPU% for process= (1- (IdleSystemTimeDelta/TotalProcessTimeDelta))*100%

  • https://learn.microsoft.com/en-us/windows/win32/perfctrs/performance-counters-portal – Hans Passant Sep 16 '21 at 21:53
  • I think you need to describe the problem you have with your current code. What does it do wrong? – Ted Lyngmo Sep 16 '21 at 21:53
  • @TedLyngmo: I think it's pretty obvious that sleeping for 5 seconds per running process (and measuring CPU utilization during a 2.5 second interval, different and non-overlapping for each process) is a problem. – Ben Voigt Sep 16 '21 at 22:19
  • 1
    @Danil First thing you need to do is interchange the two loops... you must get the "before" CPU times of all processes, then sleep once, then get the "after" CPU times. Next improvement is that on the subsequent cycle, use the "after" CPU times you already got from the prior cycle as the "before" times of the new cycle. – Ben Voigt Sep 16 '21 at 22:21
  • @BenVoigt True, that sounds bad, but is that the specific problem OP is asking about? I don't know. – Ted Lyngmo Sep 16 '21 at 22:26
  • Also, the use of `static` variables inside `CalculateCPULoad` is not going to work at all when trying to calculate load on multiple independent processes. You're going to need to track each one separately; building a state structure would be a good idea. – Ben Voigt Sep 16 '21 at 22:29
  • I have wrote static hasmaps instead and it seems to work properly,but still the difference between WinTaskManager and my version is pretty essential. – PraysforWind Sep 17 '21 at 12:38
  • I suggest you could refer to the threads: https://stackoverflow.com/questions/23143693/retrieving-cpu-load-percent-total-in-windows-with-c https://stackoverflow.com/questions/1420426/how-to-calculate-the-cpu-usage-of-a-process-by-pid-in-linux-from-c – Jeaninez - MSFT Sep 20 '21 at 06:34

1 Answers1

0

This is how i get_CPU in percent.

I use hash_map in order to have PID-time connection static to update it.

First time usage get_cpu_usage(int pid) returns zero every time,but with each next usage it will be more and more accurate(I use it with 0.5 sec period).

static int get_processor_number()
    {
        SYSTEM_INFO info;
        GetSystemInfo(&info);
        return (int)info.dwNumberOfProcessors;
    }
    static __int64 file_time_2_utc(const FILETIME* ftime)
    {
        LARGE_INTEGER li;
    
        li.LowPart = ftime->dwLowDateTime;
        li.HighPart = ftime->dwHighDateTime;
        return li.QuadPart;
    }
    static int get_cpu_usage(int pid)
    {
        static int processor_count_ = -1;
        static std::unordered_map<int, __int64> last_time_;
        static std::unordered_map<int, __int64> last_system_time_;
    
        FILETIME now;
        FILETIME creation_time;
        FILETIME exit_time;
        FILETIME kernel_time;
        FILETIME user_time;
        __int64 system_time;
        __int64 time;
        __int64 system_time_delta;
        __int64 time_delta;
    
        int cpu = -1;
    
        if (processor_count_ == -1)
        {
            processor_count_ = get_processor_number();
        }
    
        GetSystemTimeAsFileTime(&now);
    
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
        if (!GetProcessTimes(hProcess, &creation_time, &exit_time, &kernel_time, &user_time))
        {
            std::cout << "Unable to getProcessTime\n";
            return -1;
        }
        system_time = (file_time_2_utc(&kernel_time) + file_time_2_utc(&user_time)) / processor_count_;
        time = file_time_2_utc(&now);
    
        if ((last_system_time_[pid] == 0) || (last_time_[pid] == 0))
        {
            last_system_time_[pid] = system_time;
            last_time_[pid] = time;
            return 0;
        }
    
        system_time_delta = system_time - last_system_time_[pid];
        time_delta = time - last_time_[pid];
    
        if (time_delta == 0)
        {
            std::cout << "timedelta=0";
            return -1;
        }
        cpu = int((system_time_delta * 100 + time_delta / 2) / time_delta);
        last_system_time_[pid] = system_time;
        last_time_[pid] = time;
        return cpu;
    }