Как определить потребление ЦП и памяти изнутри процесса?

Однажды у меня была задача определить следующие параметры производительности из работающего приложения:

  • Общий объем доступной виртуальной памяти
  • Виртуальная память, используемая в настоящее время
  • Виртуальная память, используемая в настоящее время моим процессом
  • Общий объем доступной оперативной памяти
  • RAM в настоящее время используется
  • ОЗУ в настоящее время используется моим процессом
  • % CPU в настоящее время используется
  • % CPU в настоящее время используется моим процессом

Код должен был работать в Windows и Linux. Несмотря на то, что это кажется стандартной задачей, поиск необходимой информации в руководствах (WIN32 API, документация GNU), а также в Интернете занял у меня несколько дней, потому что существует так много неполной / неверной / устаревшей информации по этой теме. узнал там.

Я подумал, что для того, чтобы спасти других от тех же проблем, было бы неплохо собрать всю разрозненную информацию, а также то, что я нашел методом проб и ошибок, в одном месте.

«Общий объем доступной виртуальной памяти» не имеет смысла в современных операционных системах.

David Schwartz 23.12.2015 16:16

Почему это бессмысленно? Делает ли это недействительным ответ здесь? stackoverflow.com/questions/3296211/… ... пожалуйста, не оставляйте клиффхэнгеров, комментируя, это не телешоу.

Mindaugas Bernatavičius 10.12.2017 18:21

@ MindaugasBernatavičius: Связанный вопрос касается «общей физической памяти», которая является аппаратным фактом, известным ОС. Итого можно получить, сложив размеры всех модулей памяти. «Общий объем доступной виртуальной памяти», с другой стороны, что это вообще означает? Это объединенное виртуальное адресное пространство всех процессов, которые теоретически могут быть созданы? Это число будет около 2 ^ 80 байт, поэтому, конечно, бессмысленно.

MSalters 15.08.2018 14:00

@MSalters - спасибо за участие. Я считаю, что спрашивать, что имел в виду ОП, намного добрее и полезнее, чем заявлять, что что-то бессмысленно (без объяснения). Если вы заметили, ответы также предполагают определенную позицию по этому поводу: виртуальная память = RAM + SWAP (или PAGEFILE) - что является разумным предположением. Из этого мы знаем, что это не бессмысленно, поскольку существует определенная интерпретация этого термина (которая, возможно, не самая технически правильная, разговорная речь), которая имеет значение.

Mindaugas Bernatavičius 15.08.2018 16:17

@ MindaugasBernatavičius: Это игнорирует файлы с отображением памяти и код, который не выгружен. Linux имеет невыделенные распределения памяти (не поддержанные RAM или swap), а Windows имеет незафиксированные стеки.

MSalters 15.08.2018 16:23
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
635
5
334 804
10

Ответы 10

Окна

Некоторые из приведенных выше значений легко доступны из соответствующего WIN32 API, я просто перечисляю их здесь для полноты. Другие, однако, должны быть получены из библиотеки Performance Data Helper (PDH), которая немного «неинтуитивна» и требует много мучительных проб и ошибок, чтобы приступить к работе. (По крайней мере, это заняло у меня довольно много времени, возможно, я был немного глуп ...)

Примечание: для ясности в следующем коде опущена вся проверка ошибок. Проверьте коды возврата ...!


  • Общая виртуальная память:

    #include "windows.h"
    
    MEMORYSTATUSEX memInfo;
    memInfo.dwLength = sizeof(MEMORYSTATUSEX);
    GlobalMemoryStatusEx(&memInfo);
    DWORDLONG totalVirtualMem = memInfo.ullTotalPageFile;
    

    Примечание. Название TotalPageFile здесь немного вводит в заблуждение. На самом деле этот параметр дает «размер виртуальной памяти», который представляет собой размер файла подкачки плюс установленную оперативную память.

  • Виртуальная память, используемая в настоящее время:

    Тот же код, что и в «Общая виртуальная память», а затем

     DWORDLONG virtualMemUsed = memInfo.ullTotalPageFile - memInfo.ullAvailPageFile;
    
  • Виртуальная память, используемая в настоящее время текущим процессом:

    #include "windows.h"
    #include "psapi.h"
    
    PROCESS_MEMORY_COUNTERS_EX pmc;
    GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc));
    SIZE_T virtualMemUsedByMe = pmc.PrivateUsage;
    



  • Общая физическая память (ОЗУ):

    Тот же код, что и в «Общая виртуальная память», а затем

    DWORDLONG totalPhysMem = memInfo.ullTotalPhys;
    
  • Физическая память, используемая в настоящее время:

    Тот же код, что и в «Общая виртуальная память», а затем

    DWORDLONG physMemUsed = memInfo.ullTotalPhys - memInfo.ullAvailPhys;
    
  • Физическая память, используемая в настоящее время текущим процессом:

    Тот же код, что и в «Виртуальная память, используемая текущим процессом», а затем

    SIZE_T physMemUsedByMe = pmc.WorkingSetSize;
    



  • ЦП в настоящее время используется:

    #include "TCHAR.h"
    #include "pdh.h"
    
    static PDH_HQUERY cpuQuery;
    static PDH_HCOUNTER cpuTotal;
    
    void init(){
        PdhOpenQuery(NULL, NULL, &cpuQuery);
        // You can also use L"\\Processor(*)\\% Processor Time" and get individual CPU values with PdhGetFormattedCounterArray()
        PdhAddEnglishCounter(cpuQuery, L"\\Processor(_Total)\\% Processor Time", NULL, &cpuTotal);
        PdhCollectQueryData(cpuQuery);
    }
    
    double getCurrentValue(){
        PDH_FMT_COUNTERVALUE counterVal;
    
        PdhCollectQueryData(cpuQuery);
        PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal);
        return counterVal.doubleValue;
    }
    
  • ЦП в настоящее время используется текущим процессом:

    #include "windows.h"
    
    static ULARGE_INTEGER lastCPU, lastSysCPU, lastUserCPU;
    static int numProcessors;
    static HANDLE self;
    
    void init(){
        SYSTEM_INFO sysInfo;
        FILETIME ftime, fsys, fuser;
    
        GetSystemInfo(&sysInfo);
        numProcessors = sysInfo.dwNumberOfProcessors;
    
        GetSystemTimeAsFileTime(&ftime);
        memcpy(&lastCPU, &ftime, sizeof(FILETIME));
    
        self = GetCurrentProcess();
        GetProcessTimes(self, &ftime, &ftime, &fsys, &fuser);
        memcpy(&lastSysCPU, &fsys, sizeof(FILETIME));
        memcpy(&lastUserCPU, &fuser, sizeof(FILETIME));
    }
    
    double getCurrentValue(){
        FILETIME ftime, fsys, fuser;
        ULARGE_INTEGER now, sys, user;
        double percent;
    
        GetSystemTimeAsFileTime(&ftime);
        memcpy(&now, &ftime, sizeof(FILETIME));
    
        GetProcessTimes(self, &ftime, &ftime, &fsys, &fuser);
        memcpy(&sys, &fsys, sizeof(FILETIME));
        memcpy(&user, &fuser, sizeof(FILETIME));
        percent = (sys.QuadPart - lastSysCPU.QuadPart) +
            (user.QuadPart - lastUserCPU.QuadPart);
        percent /= (now.QuadPart - lastCPU.QuadPart);
        percent /= numProcessors;
        lastCPU = now;
        lastUserCPU = user;
        lastSysCPU = sys;
    
        return percent * 100;
    }
    

Linux

В Linux выбор, который сначала казался очевидным, заключался в использовании API-интерфейсов POSIX, таких как getrusage() и т. д. Я потратил некоторое время, пытаясь заставить это работать, но так и не получил значимых значений. Когда я наконец проверил сами исходные коды ядра, я обнаружил, что, по-видимому, эти API еще не полностью реализованы в ядре Linux 2.6 !?

В конце концов, я получил все значения через комбинацию чтения псевдофайловой системы /proc и вызовов ядра.

  • Общая виртуальная память:

    #include "sys/types.h"
    #include "sys/sysinfo.h"
    
    struct sysinfo memInfo;
    
    sysinfo (&memInfo);
    long long totalVirtualMem = memInfo.totalram;
    //Add other values in next statement to avoid int overflow on right hand side...
    totalVirtualMem += memInfo.totalswap;
    totalVirtualMem *= memInfo.mem_unit;
    
  • Виртуальная память, используемая в настоящее время:

    Тот же код, что и в «Общая виртуальная память», а затем

    long long virtualMemUsed = memInfo.totalram - memInfo.freeram;
    //Add other values in next statement to avoid int overflow on right hand side...
    virtualMemUsed += memInfo.totalswap - memInfo.freeswap;
    virtualMemUsed *= memInfo.mem_unit;
    
  • Виртуальная память, используемая в настоящее время текущим процессом:

    #include "stdlib.h"
    #include "stdio.h"
    #include "string.h"
    
    int parseLine(char* line){
        // This assumes that a digit will be found and the line ends in " Kb".
        int i = strlen(line);
        const char* p = line;
        while (*p <'0' || *p > '9') p++;
        line[i-3] = '\0';
        i = atoi(p);
        return i;
    }
    
    int getValue(){ //Note: this value is in KB!
        FILE* file = fopen("/proc/self/status", "r");
        int result = -1;
        char line[128];
    
        while (fgets(line, 128, file) != NULL){
            if (strncmp(line, "VmSize:", 7) == 0){
                result = parseLine(line);
                break;
            }
        }
        fclose(file);
        return result;
    }
    



  • Общая физическая память (ОЗУ):

    Тот же код, что и в «Общая виртуальная память», а затем

    long long totalPhysMem = memInfo.totalram;
    //Multiply in next statement to avoid int overflow on right hand side...
    totalPhysMem *= memInfo.mem_unit;
    
  • Физическая память, используемая в настоящее время:

    Тот же код, что и в «Общая виртуальная память», а затем

    long long physMemUsed = memInfo.totalram - memInfo.freeram;
    //Multiply in next statement to avoid int overflow on right hand side...
    physMemUsed *= memInfo.mem_unit;
    
  • Физическая память, используемая в настоящее время текущим процессом:

    Измените getValue () в «Виртуальной памяти, используемой текущим процессом» следующим образом:

    int getValue(){ //Note: this value is in KB!
        FILE* file = fopen("/proc/self/status", "r");
        int result = -1;
        char line[128];
    
        while (fgets(line, 128, file) != NULL){
            if (strncmp(line, "VmRSS:", 6) == 0){
                result = parseLine(line);
                break;
            }
        }
        fclose(file);
        return result;
    }
    



  • ЦП в настоящее время используется:

    #include "stdlib.h"
    #include "stdio.h"
    #include "string.h"
    
    static unsigned long long lastTotalUser, lastTotalUserLow, lastTotalSys, lastTotalIdle;
    
    void init(){
        FILE* file = fopen("/proc/stat", "r");
        fscanf(file, "cpu %llu %llu %llu %llu", &lastTotalUser, &lastTotalUserLow,
            &lastTotalSys, &lastTotalIdle);
        fclose(file);
    }
    
    double getCurrentValue(){
        double percent;
        FILE* file;
        unsigned long long totalUser, totalUserLow, totalSys, totalIdle, total;
    
        file = fopen("/proc/stat", "r");
        fscanf(file, "cpu %llu %llu %llu %llu", &totalUser, &totalUserLow,
            &totalSys, &totalIdle);
        fclose(file);
    
        if (totalUser < lastTotalUser || totalUserLow < lastTotalUserLow ||
            totalSys < lastTotalSys || totalIdle < lastTotalIdle){
            //Overflow detection. Just skip this value.
            percent = -1.0;
        }
        else{
            total = (totalUser - lastTotalUser) + (totalUserLow - lastTotalUserLow) +
                (totalSys - lastTotalSys);
            percent = total;
            total += (totalIdle - lastTotalIdle);
            percent /= total;
            percent *= 100;
        }
    
        lastTotalUser = totalUser;
        lastTotalUserLow = totalUserLow;
        lastTotalSys = totalSys;
        lastTotalIdle = totalIdle;
    
        return percent;
    }
    
  • ЦП в настоящее время используется текущим процессом:

    #include "stdlib.h"
    #include "stdio.h"
    #include "string.h"
    #include "sys/times.h"
    #include "sys/vtimes.h"
    
    static clock_t lastCPU, lastSysCPU, lastUserCPU;
    static int numProcessors;
    
    void init(){
        FILE* file;
        struct tms timeSample;
        char line[128];
    
        lastCPU = times(&timeSample);
        lastSysCPU = timeSample.tms_stime;
        lastUserCPU = timeSample.tms_utime;
    
        file = fopen("/proc/cpuinfo", "r");
        numProcessors = 0;
        while(fgets(line, 128, file) != NULL){
            if (strncmp(line, "processor", 9) == 0) numProcessors++;
        }
        fclose(file);
    }
    
    double getCurrentValue(){
        struct tms timeSample;
        clock_t now;
        double percent;
    
        now = times(&timeSample);
        if (now <= lastCPU || timeSample.tms_stime < lastSysCPU ||
            timeSample.tms_utime < lastUserCPU){
            //Overflow detection. Just skip this value.
            percent = -1.0;
        }
        else{
            percent = (timeSample.tms_stime - lastSysCPU) +
                (timeSample.tms_utime - lastUserCPU);
            percent /= (now - lastCPU);
            percent /= numProcessors;
            percent *= 100;
        }
        lastCPU = now;
        lastSysCPU = timeSample.tms_stime;
        lastUserCPU = timeSample.tms_utime;
    
        return percent;
    }
    

TODO: другие платформы

Я предполагаю, что часть кода Linux также работает для Unix, за исключением частей, которые читают псевдофайловую систему / proc. Может быть, в Unix эти части можно заменить на getrusage() и аналогичные функции? Если кто-то с ноу-хау Unix может отредактировать этот ответ и заполнить детали ?!

Функция parseLine () обработана.

elcuco 09.05.2009 01:26

К сожалению, скопировал код из исходного файла и не заметил, что </> нужно заменить на & lt; / & gt; ... Теперь parseLine () выглядит нормально. Кстати, странно: в этом комментарии я могу ввести «<» напрямую, и это не интерпретируется как начало HTML-тега ?! Почему не в коде ?? Там было бы гораздо больше смысла. (Тем более, что я поместил <pre> вокруг кода ... ??!)

Lanzelot 23.09.2009 15:05

Предупреждение: в PdhAddCounter запрос должен быть локализован, в противном случае он будет выполняться только в англоязычной системе. Для Vista / 2008 и более поздних версий предпочтительнее использовать PdhAddEnglishCounter, чтобы избежать проблем с локализацией.

moala 05.11.2009 16:42

В функциях getValue () для Linux (получение текущего размера процесса / rss) отсутствуют фигурные скобки в операторе if. Как бы то ни было, цикл while будет анализировать ОДНУ строку / proc / self / status перед выходом из цикла. Цикл while должен быть таким: while (fgets (строка, 128, файл)! = NULL) {if (strncmp (line, "VmSize:", 7) == 0) {result = parseLine (line); перемена; }}

Danny S 19.10.2012 08:13

@Lanzelot: Почему в ответе такое фанковое форматирование? Нет использования Markdown? Я могу это починить, если хочешь.

GManNickG 23.10.2012 02:11

Я ожидал, что будет какая-то переносимая реализация, которая сделает это. boost :: meminfo или что-то в этом роде ... @Lanzelot: вы должны это написать ;-)

krico 11.02.2013 14:49

@Lanzelot Мне кажется странным, когда я последовательно запускаю вашу функцию общего текущего использования ЦП, значение постоянно уменьшается. CPU использовал 33.0975, CPU использовал 33.0971, CPU использовал 33.0968, ... и так далее. Кстати, это двухъядерный процессор.

enthusiasticgeek 30.04.2013 00:07

Не работает на моем ubuntu 13.10 linux. Созданный файл test.cpp добавил туда код для процессора, который в настоящее время используется текущим процессом, набрал C++ -o test test.cpp и получил /usr/lib/gcc/x86_64-linux-gnu/4.6/../../../ x86_64-linux-gnu / ‌ crt1.o: в функции _start': (.text+0x20): undefined reference to main 'collect2: ld вернул 1 статус выхода

Volodymyr 30.12.2013 23:49

Требуются ли права администратора для Windows? Можно ли его получить без прав администратора?

Michael Haephrati 16.06.2015 16:56

Здравствуй. Для окон в «Физической памяти, используемой текущим процессом» я использовал PROCESS_MEMORY_COUNTERS, поскольку PROCESS_MEMORY_COUNTERS_EX не поддерживает этот интерфейс. (VS2013 / vs12). Лучший

Nuno Aniceto 05.09.2015 18:08

Я знаю, что это очень старый поток, но я столкнулся с этой проблемой. При попытке использовать использование процессора Windows в проекте, который я определил как DLL, я сталкиваюсь с этой ошибкой при компиляции: 1>System_Usage.obj : error LNK2001: unresolved external symbol _PdhOpenQueryW@12 1>System_Usage.obj : error LNK2001: unresolved external symbol _PdhAddCounterW@16 1>System_Usage.obj : error LNK2001: unresolved external symbol _PdhCollectQueryData@4 1>System_Usage.obj : error LNK2001: unresolved external symbol _PdhGetFormattedCounterValue@16

Nico 02.12.2015 15:53

Интересно, может ли кто-нибудь пролить свет на то, как выполнить эту задачу с помощью python в Linux ..,

router 15.12.2015 07:50

@NunoAniceto При использовании PROCESS_MEMORY_COUNTERS, как вы получаете "виртуальную память, в настоящее время используемую текущим процессом"? PrivateUsage не является членом PROCESS_MEMORY_COUNTERS - это ошибка компилятора, которую я получаю!

CinCout 01.03.2016 07:25

Почему вы используете "quotes like these" для включения системных заголовков?

Lightness Races in Orbit 06.06.2016 19:34

«« Размер виртуальной памяти », то есть размер файла подкачки плюс установленная оперативная память». Нет, это не виртуальная память.

Mooing Duck 20.07.2016 02:23

@CinCout вам нужно преобразование .. замените GetProcessMemoryInfo (GetCurrentProcess (), & pmc, sizeof (pmc)); с GetProcessMemoryInfo (GetCurrentProcess (), (PROCESS_MEMORY_COUNTERS *) & pmc, sizeof (pmc));

Sumia 19.08.2016 14:02

@Lanzelot С тех пор, как мы находимся выше ядра Linux 3.0. Можете ли вы обновить свой ответ Linux на POSIX API? Если возможно, исправьте также ответ Windows, заменив GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)); на GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc));.

Dr. Xperience 05.12.2016 13:35

Linux для «CPU в настоящее время используется», кажется, указывает только на среднее использование CPU с момента запуска, а не на текущее использование CPU. По крайней мере, для меня в Gentoo Linux с ядром 4.11.1-gentoo.

Josh Pinto 21.05.2017 06:37

В Linux «Используемый в настоящее время ЦП» у вас нет строки percent /= numProcessors;, как в «ЦП, который в настоящее время используется текущим процессом». Это потому, что первый уже учитывает количество процессоров? При тестировании кода кажется, что это правда, но на первый взгляд это выглядит непоследовательно. :)

Olivia Stork 29.11.2017 22:18

Для последнего, несколько портативных альтернатив /proc/cpuinfoздесь

user2975337 18.12.2017 15:37

Для Unix, если вы хотите, чтобы все это выполнялось в коде, у вас есть 2 маршрута: 1, используйте libproc (который в конечном итоге читает и форматирует / proc), или 2, напишите модуль ядра (поскольку он обращается к внутренним структурам данных ядра). Linux представляет / proc как безопасный и надежный способ доступа к информации о ядре. Я бы предположил, что Windows на самом деле делает что-то похожее на libproc с GetProcess * Info ()

Graham 10.01.2018 10:56

Для использованная оперативная память под Linux вы должны быть осторожны, потому что вы можете получить вводящие в заблуждение данные. Linux кэширует и буферизует доступную память, поэтому вы можете получить более низкие значения используемой памяти, чем ожидалось. См. Этот пост: <br/> stackoverflow.com/questions/14345937/…, вы можете использовать вывод / proc / meminfo для более подробной информации.

ficus 24.01.2019 11:13
gist.github.com/gbmhunter/00c57b55e2616cd8e1f21f77b79e59fc
sancho.s ReinstateMonicaCellio 08.02.2020 02:22

Что касается части Физическая память Windows, используемая в настоящее время текущим процессом, я думаю, что данный ответ правильный, но важно отметить, что размер рабочего набора - это не совсем оперативная память, используемая процессом для его работы, потому что он учитывает как частные, так и общие рабочие наборы. Подробнее здесь: docs.microsoft.com/en-us/windows/win32/memory/working-set. Я все еще пытаюсь найти способ измерить размер частного рабочего набора, который, на мой взгляд, более точно соответствует обозначению «Физическая память, используемая текущим процессом».

Spazz 23.08.2020 17:13

И пока мои исследования основаны на этих двух сообщениях CodeProject и Переполнение стека, которые, кажется, дают ответ на вопрос, как измерить размер частного рабочего набора, но мне все еще нужно попробовать. Просто оставьте это здесь для тех, кто заинтересован в измерении размера частного рабочего набора.

Spazz 23.08.2020 17:18

Linux

В Linux эта информация доступна в файловой системе / proc. Я не большой поклонник используемого формата текстовых файлов, поскольку каждый дистрибутив Linux настраивает как минимум один важный файл. Быстрый взгляд на источник "ps" обнаруживает беспорядок.

Но вот где найти нужную информацию:

/ proc / meminfo содержит большую часть общесистемной информации, которую вы ищете. Вот это похоже на мою систему; Думаю, вас интересуют MemTotal, MemFree, SwapTotal и SwapFree:

Anderson cxC# more /proc/meminfo
MemTotal:      4083948 kB
MemFree:       2198520 kB
Buffers:         82080 kB
Cached:        1141460 kB
SwapCached:          0 kB
Active:        1137960 kB
Inactive:       608588 kB
HighTotal:     3276672 kB
HighFree:      1607744 kB
LowTotal:       807276 kB
LowFree:        590776 kB
SwapTotal:     2096440 kB
SwapFree:      2096440 kB
Dirty:              32 kB
Writeback:           0 kB
AnonPages:      523252 kB
Mapped:          93560 kB
Slab:            52880 kB
SReclaimable:    24652 kB
SUnreclaim:      28228 kB
PageTables:       2284 kB
NFS_Unstable:        0 kB
Bounce:              0 kB
CommitLimit:   4138412 kB
Committed_AS:  1845072 kB
VmallocTotal:   118776 kB
VmallocUsed:      3964 kB
VmallocChunk:   112860 kB
HugePages_Total:     0
HugePages_Free:      0
HugePages_Rsvd:      0
Hugepagesize:     2048 kB

Для загрузки ЦП вам нужно немного поработать. Linux делает доступным общее использование ЦП с момента запуска системы; вероятно, это не то, что вас интересует. Если вы хотите узнать, какова была загрузка ЦП в последнюю секунду или 10 секунд, вам нужно запросить информацию и вычислить ее самостоятельно.

Информация доступна в / proc / stat, который довольно хорошо документирован в http://www.linuxhowtos.org/System/procstat.htm; вот как это выглядит на моем 4-ядерном ящике:

Anderson cxC#  more /proc/stat
cpu  2329889 0 2364567 1063530460 9034 9463 96111 0
cpu0 572526 0 636532 265864398 2928 1621 6899 0
cpu1 590441 0 531079 265949732 4763 351 8522 0
cpu2 562983 0 645163 265796890 682 7490 71650 0
cpu3 603938 0 551790 265919440 660 0 9040 0
intr 37124247
ctxt 50795173133
btime 1218807985
processes 116889
procs_running 1
procs_blocked 0

Во-первых, вам нужно определить, сколько процессоров (или процессоров, или процессорных ядер) доступно в системе. Для этого подсчитайте количество записей cpuN, где N начинается с 0 и увеличивается. Не считайте строку «cpu», которая представляет собой комбинацию строк cpuN. В моем примере вы можете видеть от cpu0 до cpu3, ​​всего 4 процессора. С этого момента вы можете игнорировать cpu0..cpu3 и сосредоточиться только на строке cpu.

Затем вам нужно знать, что четвертое число в этих строках является мерой времени простоя, и, таким образом, четвертое число в строке «cpu» - это общее время простоя для всех процессоров с момента загрузки. Это время измеряется в «jiffies» Linux, каждая из которых составляет 1/100 секунды.

Но вам наплевать на общее время простоя; вас волнует время простоя в определенный период, например, последняя секунда. Подсчитайте, вам нужно прочитать этот файл дважды, с интервалом в 1 секунду. Затем вы можете сделать разницу четвертого значения в строке. Например, если взять пробу и получить:

cpu  2330047 0 2365006 1063853632 9035 9463 96114 0

Через секунду вы получите этот образец:

cpu  2330047 0 2365007 1063854028 9035 9463 96114 0

Вычтите два числа, и вы получите разницу в 396, что означает, что ваш процессор простаивал 3,96 секунды из последних 1,00 секунды. Уловка, конечно же, в том, что вам нужно разделить на количество процессоров. 3,96 / 4 = 0,99, и вот ваш процент простоя; 99% простаивает и 1% занято.

В моем коде у меня есть кольцевой буфер на 360 записей, и я читаю этот файл каждую секунду. Это позволяет мне быстро рассчитать загрузку ЦП за 1 секунду, 10 секунд и т. д., Вплоть до 1 часа.

Информацию о процессе вы должны искать в / proc / pid; если вас не волнует ваш pid, вы можете заглянуть в / proc / self.

ЦП, используемый вашим процессом, доступен в / proc / self / stat. Это файл со странным внешним видом, состоящий из одной строки; Например:

19340 (whatever) S 19115 19115 3084 34816 19115 4202752 118200 607 0 0 770 384 2
 7 20 0 77 0 266764385 692477952 105074 4294967295 134512640 146462952 321468364
8 3214683328 4294960144 0 2147221247 268439552 1276 4294967295 0 0 17 0 0 0 0

Важными данными здесь являются 13-й и 14-й токены (здесь 0 и 770). 13-й токен - это количество переходов, которые процесс выполнил в пользовательском режиме, а 14-й - это количество переходов, которые процесс выполнил в режиме ядра. Сложите их вместе, и вы получите полную загрузку ЦП.

Опять же, вам придется периодически выполнять выборку этого файла и вычислять разницу, чтобы определять использование ЦП процессом с течением времени.

Редактировать: помните, что когда вы рассчитываете использование ЦП своим процессом, вы должны учитывать 1) количество потоков в вашем процессе и 2) количество процессоров в системе. Например, если ваш однопоточный процесс использует только 25% ЦП, это может быть хорошо или плохо. Хорошо на однопроцессорной системе, но плохо на 4-процессорной системе; это означает, что ваш процесс работает постоянно и использует 100% доступных ему циклов ЦП.

Для получения информации о памяти, связанной с конкретным процессом, вам нужно посмотреть / proc / self / status, который выглядит следующим образом:

Name:   whatever
State:  S (sleeping)
Tgid:   19340
Pid:    19340
PPid:   19115
TracerPid:      0
Uid:    0       0       0       0
Gid:    0       0       0       0
FDSize: 256
Groups: 0 1 2 3 4 6 10 11 20 26 27
VmPeak:   676252 kB
VmSize:   651352 kB
VmLck:         0 kB
VmHWM:    420300 kB
VmRSS:    420296 kB
VmData:   581028 kB
VmStk:       112 kB
VmExe:     11672 kB
VmLib:     76608 kB
VmPTE:      1244 kB
Threads:        77
SigQ:   0/36864
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: fffffffe7ffbfeff
SigIgn: 0000000010001000
SigCgt: 20000001800004fc
CapInh: 0000000000000000
CapPrm: 00000000ffffffff
CapEff: 00000000fffffeff
Cpus_allowed:   0f
Mems_allowed:   1
voluntary_ctxt_switches:        6518
nonvoluntary_ctxt_switches:     6598

Записи, начинающиеся с 'Vm', представляют интерес:

  • VmPeak - это максимальное пространство виртуальной памяти, используемое процессом, в килобайтах (1024 байта).
  • VmSize - это текущее пространство виртуальной памяти, используемое процессом, в килобайтах. В моем примере он довольно большой: 651 352 кБ или около 636 мегабайт.
  • VmRss - это объем памяти, отображаемый в адресное пространство процесса, или размер его резидентного набора. Это существенно меньше (420 296 КБ, или около 410 мегабайт). Разница: моя программа отобразила 636 МБ через mmap (), но получила доступ только к 410 МБ из них, и, таким образом, ей было назначено только 410 МБ страниц.

Единственный предмет, в котором я не уверен, - это Пространство подкачки, используемое в настоящее время моим процессом. Не знаю, доступно ли это.

Спасибо, Мартин, если бы вся эта информация была собрана в одном месте, это сэкономило бы мне пару бессонных ночей ... Однако для CPU текущего процесса я думаю, что функция times () - более простой и надежный подход. Кстати: пространство подкачки текущего процесса = VmSize - VmRSS, не так ли?

Lanzelot 16.09.2008 12:27

Mac OS X

Я надеялся найти аналогичную информацию и для Mac OS X. Поскольку его здесь не было, я сам пошел и откопал его. Вот некоторые из вещей, которые я нашел. Если у кого-то есть другие предложения, я хотел бы их услышать.

Общая виртуальная память

Это сложно в Mac OS X, потому что в нем не используется предустановленный раздел или файл подкачки, как в Linux. Вот запись из документации Apple:

Note: Unlike most Unix-based operating systems, Mac OS X does not use a preallocated swap partition for virtual memory. Instead, it uses all of the available space on the machine’s boot partition.

Итак, если вы хотите узнать, сколько виртуальной памяти все еще доступно, вам нужно получить размер корневого раздела. Сделать это можно так:

struct statfs stats;
if (0 == statfs("/", &stats))
{
    myFreeSwap = (uint64_t)stats.f_bsize * stats.f_bfree;
}

Всего виртуальных ресурсов, используемых в настоящее время

Вызов systcl с ключом "vm.swapusage" дает интересную информацию об использовании подкачки:

sysctl -n vm.swapusage
vm.swapusage: total = 3072.00M  used = 2511.78M  free = 560.22M  (encrypted)

Не то, чтобы отображаемое здесь общее использование свопа может измениться, если потребуется больше свопа, как описано в разделе выше. Таким образом, общая сумма фактически равна сумме свопа Текущий. В C++ эти данные можно запросить следующим образом:

xsw_usage vmusage = {0};
size_t size = sizeof(vmusage);
if ( sysctlbyname("vm.swapusage", &vmusage, &size, NULL, 0)!=0 )
{
   perror( "unable to get swap usage by calling sysctlbyname(\"vm.swapusage\",...)" );
}

Обратите внимание, что «xsw_usage», объявленный в sysctl.h, не задокументирован, и я подозреваю, что существует более переносимый способ доступа к этим значениям.

Виртуальная память, используемая в настоящее время моим процессом

Вы можете получить статистику о текущем процессе, используя функцию task_info. Это включает в себя текущий резидентный размер вашего процесса и текущий виртуальный размер.

#include<mach/mach.h>

struct task_basic_info t_info;
mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;

if (KERN_SUCCESS != task_info(mach_task_self(),
                              TASK_BASIC_INFO, (task_info_t)&t_info, 
                              &t_info_count))
{
    return -1;
}
// resident size is in t_info.resident_size;
// virtual size is in t_info.virtual_size;

Общий объем доступной оперативной памяти

Объем физической оперативной памяти, доступной в вашей системе, можно получить с помощью системной функции sysctl следующим образом:

#include <sys/types.h>
#include <sys/sysctl.h>
...
int mib[2];
int64_t physical_memory;
mib[0] = CTL_HW;
mib[1] = HW_MEMSIZE;
length = sizeof(int64_t);
sysctl(mib, 2, &physical_memory, &length, NULL, 0);

RAM в настоящее время используется

Вы можете получить общую статистику памяти с помощью системной функции host_statistics.

#include <mach/vm_statistics.h>
#include <mach/mach_types.h>
#include <mach/mach_init.h>
#include <mach/mach_host.h>

int main(int argc, const char * argv[]) {
    vm_size_t page_size;
    mach_port_t mach_port;
    mach_msg_type_number_t count;
    vm_statistics64_data_t vm_stats;

    mach_port = mach_host_self();
    count = sizeof(vm_stats) / sizeof(natural_t);
    if (KERN_SUCCESS == host_page_size(mach_port, &page_size) &&
        KERN_SUCCESS == host_statistics64(mach_port, HOST_VM_INFO,
                                        (host_info64_t)&vm_stats, &count))
    {
        long long free_memory = (int64_t)vm_stats.free_count * (int64_t)page_size;

        long long used_memory = ((int64_t)vm_stats.active_count +
                                 (int64_t)vm_stats.inactive_count +
                                 (int64_t)vm_stats.wire_count) *  (int64_t)page_size;
        printf("free memory: %lld\nused memory: %lld\n", free_memory, used_memory);
    }

    return 0;
}

Следует отметить, что в Mac OS X существует пять типов страниц памяти. Они следующие:

  1. Проводной страницы, которые заблокированы на месте и не могут быть заменены
  2. Страницы Активный, которые загружаются в физическую память, и их будет относительно сложно заменить
  3. Страницы Неактивный, которые загружены в память, но не использовались в последнее время и могут даже не понадобиться. Это потенциальные кандидаты на обмен. Возможно, эту память необходимо очистить.
  4. Страницы Кешировано, которые были каким-то образом кэшированы, и которые, вероятно, будут легко повторно использованы. Кэшированная память, вероятно, не требует промывки. По-прежнему можно повторно активировать кешированные страницы.
  5. Свободный страниц, которые полностью бесплатны и готовы к использованию.

Стоит отметить, что только потому, что Mac OS X может иногда показывать очень мало фактической свободной памяти, это не может быть хорошим показателем того, сколько памяти можно использовать в короткие сроки.

RAM в настоящее время используется моим процессом

См. Выше «Виртуальная память, используемая моим процессом». Применяется тот же код.

Вы остановили #include <mach / mach.h>, чтобы определить task_info () в разделе «Виртуальная память, используемая моим процессом в настоящее время». Этот заголовок необходимо включить для определения этой функции.

Dan Nissenbaum 14.02.2011 00:58

Есть идеи об использовании ЦП?

Mihir Mehta 20.05.2013 17:34

@Michael Taylor, это большое спасибо, но вопрос об оперативной памяти, используемой в настоящее время для OS X, похоже, вы получаете статистику виртуальной машины, а не физической памяти. Так ли это на самом деле?

Edgar Aroutiounian 25.12.2014 02:49

@EdgarAroutiounian Система vm управляет памятью, поэтому вы запрашиваете ее. Статистика памяти относится к фактической памяти. Я провел тест на своей машине, и в статистике отсутствует часть физической памяти (они не складываются с моей физической памятью). Хотя они, похоже, не включают мой своп. К сожалению, вы можете читать только заголовки документов.

Michael Taylor 30.12.2014 07:33

Как мы можем рассчитать память приложения и кеш-память, такую ​​как монитор активности? Я использовал vm_stats.inactive_page_count * page_size t вычислить кеш файлов, но он не синхронизируется с монитором активности. заранее спасибо

Amit Khandelwal 18.07.2015 04:43

первоначальный автор, кажется, сбит с толку насчет «виртуальной памяти» - в некоторых контекстах это относится не к памяти подкачки на диск, а к виртуальному адресному пространству, которое может быть не полностью выгруженным. Найдите систему, в которой не используется свопинг, и вы увидите, что большинство процессов имеют больший размер virt, чем размер rss. В разделе «Виртуальная память, используемая в настоящее время моим процессом» это то, что означает «виртуальная память» - адресное пространство, а не память, выгружаемая на диск.

Pierce 01.09.2016 04:00

в Windows вы можете получить использование процессора с помощью кода ниже:

#include <windows.h>
#include <stdio.h>

    //------------------------------------------------------------------------------------------------------------------
    // Prototype(s)...
    //------------------------------------------------------------------------------------------------------------------
    CHAR cpuusage(void);

    //-----------------------------------------------------
    typedef BOOL ( __stdcall * pfnGetSystemTimes)( LPFILETIME lpIdleTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime );
    static pfnGetSystemTimes s_pfnGetSystemTimes = NULL;

    static HMODULE s_hKernel = NULL;
    //-----------------------------------------------------
    void GetSystemTimesAddress()
    {
        if ( s_hKernel == NULL )
        {   
            s_hKernel = LoadLibrary( L"Kernel32.dll" );
            if ( s_hKernel != NULL )
            {
                s_pfnGetSystemTimes = (pfnGetSystemTimes)GetProcAddress( s_hKernel, "GetSystemTimes" );
                if ( s_pfnGetSystemTimes == NULL )
                {
                    FreeLibrary( s_hKernel ); s_hKernel = NULL;
                }
            }
        }
    }
    //----------------------------------------------------------------------------------------------------------------

    //----------------------------------------------------------------------------------------------------------------
    // cpuusage(void)
    // ==============
    // Return a CHAR value in the range 0 - 100 representing actual CPU usage in percent.
    //----------------------------------------------------------------------------------------------------------------
    CHAR cpuusage()
    {
        FILETIME               ft_sys_idle;
        FILETIME               ft_sys_kernel;
        FILETIME               ft_sys_user;

        ULARGE_INTEGER         ul_sys_idle;
        ULARGE_INTEGER         ul_sys_kernel;
        ULARGE_INTEGER         ul_sys_user;

        static ULARGE_INTEGER    ul_sys_idle_old;
        static ULARGE_INTEGER  ul_sys_kernel_old;
        static ULARGE_INTEGER  ul_sys_user_old;

        CHAR  usage = 0;

        // we cannot directly use GetSystemTimes on C language
        /* add this line :: pfnGetSystemTimes */
        s_pfnGetSystemTimes(&ft_sys_idle,    /* System idle time */
            &ft_sys_kernel,  /* system kernel time */
            &ft_sys_user);   /* System user time */

        CopyMemory(&ul_sys_idle  , &ft_sys_idle  , sizeof(FILETIME)); // Could been optimized away...
        CopyMemory(&ul_sys_kernel, &ft_sys_kernel, sizeof(FILETIME)); // Could been optimized away...
        CopyMemory(&ul_sys_user  , &ft_sys_user  , sizeof(FILETIME)); // Could been optimized away...

        usage  =
            (
            (
            (
            (
            (ul_sys_kernel.QuadPart - ul_sys_kernel_old.QuadPart)+
            (ul_sys_user.QuadPart   - ul_sys_user_old.QuadPart)
            )
            -
            (ul_sys_idle.QuadPart-ul_sys_idle_old.QuadPart)
            )
            *
            (100)
            )
            /
            (
            (ul_sys_kernel.QuadPart - ul_sys_kernel_old.QuadPart)+
            (ul_sys_user.QuadPart   - ul_sys_user_old.QuadPart)
            )
            );

        ul_sys_idle_old.QuadPart   = ul_sys_idle.QuadPart;
        ul_sys_user_old.QuadPart   = ul_sys_user.QuadPart;
        ul_sys_kernel_old.QuadPart = ul_sys_kernel.QuadPart;

        return usage;
    }
    //------------------------------------------------------------------------------------------------------------------
    // Entry point
    //------------------------------------------------------------------------------------------------------------------
    int main(void)
    {
        int n;
        GetSystemTimesAddress();
        for(n=0;n<20;n++)
        {
            printf("CPU Usage: %3d%%\r",cpuusage());
            Sleep(2000);
        }
        printf("\n");
        return 0;
    }

можно ли это изменить для внешней функции DLL, которую я могу позже вызвать в C#?

Nico 02.12.2015 15:55

Форматирование usage = - самая креативная вещь, которую я когда-либо видел, совсем не читаемая, но креативная.

ViRuSTriNiTy 26.05.2016 17:45

Предупреждение: выражение в приведенном выше коде, вычисляющее «использование», неверно. Если система простаивает, она делится на ноль. В случае, если время простоя было равно времени пользователя + времени ядра, будет получено 0, а не 50%, как можно было бы ожидать.

Andrei Belogortseff 31.12.2016 20:46

Также имейте в виду, что согласно текущему MSDN, время ядра также включает время простоя!

Andrei Belogortseff 31.12.2016 22:38

@sayyedmohsenzahraee: Я не рассматривал логику этого, просто комментарий к самому коду. 1) Используйте простые 64-битные переменные вместо объединения, то есть ULONGLONG для VS вместо ULARGE_INTEGER. 2) Вы слишком усложняете ситуацию, вызывая CopyMemory(), вместо этого просто используйте ULONGLONG ul_sys_idle = *(ULONGLONG*)&ft_sys_idle;. Он будет переведен в одну инструкцию CPU mov (или lea).

ahmd0 09.12.2017 04:44

QNX

Поскольку это похоже на «википедию кода», я хочу добавить код из базы знаний QNX (примечание: это не моя работа, но я проверил ее, и она отлично работает в моей системе):

Как получить использование ЦП в%: http://www.qnx.com/support/knowledgebase.html?id=50130000000P9b5

#include <atomic.h>
#include <libc.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/iofunc.h>
#include <sys/neutrino.h>
#include <sys/resmgr.h>
#include <sys/syspage.h>
#include <unistd.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/debug.h>
#include <sys/procfs.h>
#include <sys/syspage.h>
#include <sys/neutrino.h>
#include <sys/time.h>
#include <time.h>
#include <fcntl.h>
#include <devctl.h>
#include <errno.h>

#define MAX_CPUS 32

static float Loads[MAX_CPUS];
static _uint64 LastSutime[MAX_CPUS];
static _uint64 LastNsec[MAX_CPUS];
static int ProcFd = -1;
static int NumCpus = 0;


int find_ncpus(void) {
    return NumCpus;
}

int get_cpu(int cpu) {
    int ret;
    ret = (int)Loads[ cpu % MAX_CPUS ];
    ret = max(0,ret);
    ret = min(100,ret);
    return( ret );
}

static _uint64 nanoseconds( void ) {
    _uint64 sec, usec;
    struct timeval tval;
    gettimeofday( &tval, NULL );
    sec = tval.tv_sec;
    usec = tval.tv_usec;
    return( ( ( sec * 1000000 ) + usec ) * 1000 );
}

int sample_cpus( void ) {
    int i;
    debug_thread_t debug_data;
    _uint64 current_nsec, sutime_delta, time_delta;
    memset( &debug_data, 0, sizeof( debug_data ) );
    
    for( i=0; i<NumCpus; i++ ) {
        /* Get the sutime of the idle thread #i+1 */
        debug_data.tid = i + 1;
        devctl( ProcFd, DCMD_PROC_TIDSTATUS,
        &debug_data, sizeof( debug_data ), NULL );
        /* Get the current time */
        current_nsec = nanoseconds();
        /* Get the deltas between now and the last samples */
        sutime_delta = debug_data.sutime - LastSutime[i];
        time_delta = current_nsec - LastNsec[i];
        /* Figure out the load */
        Loads[i] = 100.0 - ( (float)( sutime_delta * 100 ) / (float)time_delta );
        /* Flat out strange rounding issues. */
        if ( Loads[i] < 0 ) {
            Loads[i] = 0;
        }
        /* Keep these for reference in the next cycle */
        LastNsec[i] = current_nsec;
        LastSutime[i] = debug_data.sutime;
    }
    return EOK;
}

int init_cpu( void ) {
    int i;
    debug_thread_t debug_data;
    memset( &debug_data, 0, sizeof( debug_data ) );
/* Open a connection to proc to talk over.*/
    ProcFd = open( "/proc/1/as", O_RDONLY );
    if ( ProcFd == -1 ) {
        fprintf( stderr, "pload: Unable to access procnto: %s\n",strerror( errno ) );
        fflush( stderr );
        return -1;
    }
    i = fcntl(ProcFd,F_GETFD);
    if (i != -1){
        i |= FD_CLOEXEC;
        if (fcntl(ProcFd,F_SETFD,i) != -1){
            /* Grab this value */
            NumCpus = _syspage_ptr->num_cpu;
            /* Get a starting point for the comparisons */
            for( i=0; i<NumCpus; i++ ) {
                /*
                * the sutime of idle thread is how much
                * time that thread has been using, we can compare this
                * against how much time has passed to get an idea of the
                * load on the system.
                */
                debug_data.tid = i + 1;
                devctl( ProcFd, DCMD_PROC_TIDSTATUS, &debug_data, sizeof( debug_data ), NULL );
                LastSutime[i] = debug_data.sutime;
                LastNsec[i] = nanoseconds();
            }
            return(EOK);
        }
    }
    close(ProcFd);
    return(-1);
}

void close_cpu(void){
    if (ProcFd != -1){
        close(ProcFd);
        ProcFd = -1;
    }
}

int main(int argc, char* argv[]){
    int i,j;
    init_cpu();
    printf("System has: %d CPUs\n", NumCpus);
    for(i=0; i<20; i++) {
        sample_cpus();
        for(j=0; j<NumCpus;j++)
        printf("CPU #%d: %f\n", j, Loads[j]);
        sleep(1);
    }
    close_cpu();
}

Как получить свободную (!) Память: http://www.qnx.com/support/knowledgebase.html?id=50130000000mlbx

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <err.h>
#include <sys/stat.h>
#include <sys/types.h>

int main( int argc, char *argv[] ){
    struct stat statbuf;
    paddr_t freemem;
    stat( "/proc", &statbuf );
    freemem = (paddr_t)statbuf.st_size;
    printf( "Free memory: %d bytes\n", freemem );
    printf( "Free memory: %d KB\n", freemem / 1024 );
    printf( "Free memory: %d MB\n", freemem / ( 1024 * 1024 ) );
    return 0;
} 

Linux

Портативный способ чтения памяти и номеров загрузки - sysinfo звонок

использование

   #include <sys/sysinfo.h>

   int sysinfo(struct sysinfo *info);

ОПИСАНИЕ

   Until Linux 2.3.16, sysinfo() used to return information in the
   following structure:

       struct sysinfo {
           long uptime;             /* Seconds since boot */
           unsigned long loads[3];  /* 1, 5, and 15 minute load averages */
           unsigned long totalram;  /* Total usable main memory size */
           unsigned long freeram;   /* Available memory size */
           unsigned long sharedram; /* Amount of shared memory */
           unsigned long bufferram; /* Memory used by buffers */
           unsigned long totalswap; /* Total swap space size */
           unsigned long freeswap;  /* swap space still available */
           unsigned short procs;    /* Number of current processes */
           char _f[22];             /* Pads structure to 64 bytes */
       };

   and the sizes were given in bytes.

   Since Linux 2.3.23 (i386), 2.3.48 (all architectures) the structure
   is:

       struct sysinfo {
           long uptime;             /* Seconds since boot */
           unsigned long loads[3];  /* 1, 5, and 15 minute load averages */
           unsigned long totalram;  /* Total usable main memory size */
           unsigned long freeram;   /* Available memory size */
           unsigned long sharedram; /* Amount of shared memory */
           unsigned long bufferram; /* Memory used by buffers */
           unsigned long totalswap; /* Total swap space size */
           unsigned long freeswap;  /* swap space still available */
           unsigned short procs;    /* Number of current processes */
           unsigned long totalhigh; /* Total high memory size */
           unsigned long freehigh;  /* Available high memory size */
           unsigned int mem_unit;   /* Memory unit size in bytes */
           char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding to 64 bytes */
       };

   and the sizes are given as multiples of mem_unit bytes.

Я использовал этот следующий код в своем проекте на C++, и он отлично работал:

static HANDLE self;
static int numProcessors;
SYSTEM_INFO sysInfo;

double percent;

numProcessors = sysInfo.dwNumberOfProcessors;

//Getting system times information
FILETIME SysidleTime;
FILETIME SyskernelTime; 
FILETIME SysuserTime; 
ULARGE_INTEGER SyskernelTimeInt, SysuserTimeInt;
GetSystemTimes(&SysidleTime, &SyskernelTime, &SysuserTime);
memcpy(&SyskernelTimeInt, &SyskernelTime, sizeof(FILETIME));
memcpy(&SysuserTimeInt, &SysuserTime, sizeof(FILETIME));
__int64 denomenator = SysuserTimeInt.QuadPart + SyskernelTimeInt.QuadPart;  

//Getting process times information
FILETIME ProccreationTime, ProcexitTime, ProcKernelTime, ProcUserTime;
ULARGE_INTEGER ProccreationTimeInt, ProcexitTimeInt, ProcKernelTimeInt, ProcUserTimeInt;
GetProcessTimes(self, &ProccreationTime, &ProcexitTime, &ProcKernelTime, &ProcUserTime);
memcpy(&ProcKernelTimeInt, &ProcKernelTime, sizeof(FILETIME));
memcpy(&ProcUserTimeInt, &ProcUserTime, sizeof(FILETIME));
__int64 numerator = ProcUserTimeInt.QuadPart + ProcKernelTimeInt.QuadPart;
//QuadPart represents a 64-bit signed integer (ULARGE_INTEGER)

percent = 100*(numerator/denomenator);

Разве у вас нет таких значений, как 0,00%, и значений, превышающих 100% с помощью этого механизма?

Buddhika Chaturanga 17.11.2017 09:49

Это для Mac OS?

RuLoViC 14.11.2018 02:53

@RuLoViC Это для Windows.

nonrectangular 12.06.2019 01:45

Для Linux Вы также можете использовать / proc / self / statm, чтобы получить одну строку чисел, содержащую ключевую информацию о памяти процесса, которая обрабатывается быстрее, чем просмотр длинного списка сообщаемой информации, полученной из proc / self / status.

См. http://man7.org/linux/man-pages/man5/proc.5.html

   /proc/[pid]/statm
          Provides information about memory usage, measured in pages.
          The columns are:

              size       (1) total program size
                         (same as VmSize in /proc/[pid]/status)
              resident   (2) resident set size
                         (same as VmRSS in /proc/[pid]/status)
              shared     (3) number of resident shared pages (i.e., backed by a file)
                         (same as RssFile+RssShmem in /proc/[pid]/status)
              text       (4) text (code)
              lib        (5) library (unused since Linux 2.6; always 0)
              data       (6) data + stack
              dt         (7) dirty pages (unused since Linux 2.6; always 0)

Кто-нибудь знает, насколько надежен общий размер, указанный на страницах? Это фактическое место в памяти в страницах?

niken 24.07.2017 19:22

Mac OS X - ЦП

Общая загрузка ЦП:

От Получить системную информацию о MacOS X?:

#include <mach/mach_init.h>
#include <mach/mach_error.h>
#include <mach/mach_host.h>
#include <mach/vm_map.h>

static unsigned long long _previousTotalTicks = 0;
static unsigned long long _previousIdleTicks = 0;

// Returns 1.0f for "CPU fully pinned", 0.0f for "CPU idle", or somewhere in between
// You'll need to call this at regular intervals, since it measures the load between
// the previous call and the current one.
float GetCPULoad()
{
   host_cpu_load_info_data_t cpuinfo;
   mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
   if (host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)&cpuinfo, &count) == KERN_SUCCESS)
   {
      unsigned long long totalTicks = 0;
      for(int i=0; i<CPU_STATE_MAX; i++) totalTicks += cpuinfo.cpu_ticks[i];
      return CalculateCPULoad(cpuinfo.cpu_ticks[CPU_STATE_IDLE], totalTicks);
   }
   else return -1.0f;
}

float CalculateCPULoad(unsigned long long idleTicks, unsigned long long totalTicks)
{
  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;
}

В Linux вы не можете / не должны получать «Общий объем доступной физической памяти» с помощью свободной памяти SysInfo или выполняя некоторые арифметические операции с totalram. Рекомендуемый способ сделать это - прочитать proc / meminfo, указав https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773:

Many load balancing and workload placing programs check /proc/meminfo to estimate how much free memory is available. They generally do this by adding up "free" and "cached", which was fine ten years ago, but is pretty much guaranteed to be wrong today.

It is more convenient to provide such an estimate in /proc/meminfo. If things change in the future, we only have to change it in one place.

Один из способов сделать это, как предлагает https://stackoverflow.com/a/350039/7984460: прочитать файл и использовать fscanf, чтобы захватить строку (но вместо того, чтобы использовать MemTotal, выберите MemAvailable)

Точно так же, если вы хотите получить общий объем используемой физической памяти, в зависимости от того, что вы подразумеваете под «использованием», вы можете не вычитать freeram из totalram, а вычесть memavailable из memtotal, чтобы получить то, что вам сообщает top / htop.

Другие вопросы по теме