How to determine CPU and memory consumption from inside a process

本文详细介绍了如何在Windows和Linux环境下获取系统资源使用情况的方法,包括总虚拟内存、当前使用的虚拟内存、当前进程使用的虚拟内存、总物理内存、当前使用的物理内存、当前进程使用的物理内存以及CPU使用率等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • Total virtual memory available
  • Virtual memory currently used
  • Virtual memory currently used by my process
  • Total RAM available
  • RAM currently used
  • RAM currently used by my process
  • % CPU currently used
  • % CPU currently used by my process

Windows

Some of the above values are easily available from the appropriate WIN32 API, I just list them here for completeness. Others, however, need to be obtained from the Performance Data Helper libary (PDH), which is a bit "unintuitive" and takes a lot of painful trial and error to get to work. (At least it took me quite a while, perhaps I've been only a bit stupid...)

Note: for clarity all error checking has been omitted from the following code. Do check the return codes...!


  • Total Virtual Memory:

    #include "windows.h"
    

    MEMORYSTATUSEX memInfo;
    memInfo.dwLength = sizeof(MEMORYSTATUSEX);
    GlobalMemoryStatusEx(&memInfo);
    DWORDLONG totalVirtualMem = memInfo.ullTotalPageFile;

Note: The name "TotalPageFile" is a bit misleading here. In reality this parameter gives the "Virtual Memory Size", which is size of swap file plus installed RAM.

  • Virtual Memory currently used:

Same code as in "Total Virtual Memory" and then


    DWORDLONG virtualMemUsed = memInfo.ullTotalPageFile - memInfo.ullAvailPageFile;
  • Virtual Memory currently used by current process:

    #include "windows.h"
    #include "psapi.h"
    

    PROCESS_MEMORY_COUNTERS_EX pmc;
    GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
    SIZE_T virtualMemUsedByMe = pmc.PrivateUsage;



  • Total Physical Memory (RAM):

Same code as in "Total Virtual Memory" and then


    DWORDLONG totalPhysMem = memInfo.ullTotalPhys;
  • Physical Memory currently used:

Same code as in "Total Virtual Memory" and then


    DWORDLONG physMemUsed = memInfo.ullTotalPhys - memInfo.ullAvailPhys;
  • Physical Memory currently used by current process:

Same code as in "Virtual Memory currently used by current process" and then


    SIZE_T physMemUsedByMe = pmc.WorkingSetSize;



  • CPU currently used:

    #include "TCHAR.h"
    #include "pdh.h"
    

    static PDH_HQUERY cpuQuery;
    static PDH_HCOUNTER cpuTotal;
    

    void init(){
        PdhOpenQuery(NULL, NULL, &cpuQuery);
        PdhAddCounter(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;
    }
  • CPU currently used by current process:

    #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

On Linux the choice that seemed obvious at first was to use the POSIX APIs like getrusage() etc. I spent some time trying to get this to work, but never got meaningful values. When I finally checked the kernel sources themselves, I found out that apparently these APIs are not yet completely implemented as of Linux kernel 2.6!?

In the end I got all values via a combination of reading the pseudo-filesystem /proc and kernel calls.

  • Total Virtual Memory:

    #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;
  • Virtual Memory currently used:

Same code as in "Total Virtual Memory" and then


    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;
  • Virtual Memory currently used by current process:

    #include "stdlib.h"
    #include "stdio.h"
    #include "string.h"
    

    int parseLine(char* line){
        int i = strlen(line);
        while (*line < '0' || *line > '9') line++;
        line[i-3] = '\0';
        i = atoi(line);
        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;
    }



  • Total Physical Memory (RAM):

Same code as in "Total Virtual Memory" and then


    long long totalPhysMem = memInfo.totalram;
    //Multiply in next statement to avoid int overflow on right hand side...
    totalPhysMem *= memInfo.mem_unit;
  • Physical Memory currently used:

Same code as in "Total Virtual Memory" and then


    long long physMemUsed = memInfo.totalram - memInfo.freeram;
    //Multiply in next statement to avoid int overflow on right hand side...
    physMemUsed *= memInfo.mem_unit;
  • Physical Memory currently used by current process:

Change getValue() in "Virtual Memory currently used by current process" as follows:


    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;
    }



  • CPU currently used:

    #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 %Ld %Ld %Ld %Ld", &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 %Ld %Ld %Ld %Ld", &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;
    }
  • CPU currently used by current process:

    #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;
    }

 

GlobalMemoryStatus

GlobalMemoryStatus,Win32 API函数。

此函数用来获得当前可用的物理和虚拟内存信息,函数定义为:

?

1

2

3

4

VOID GlobalMemoryStatus

(

LPMEMORYSTATUS lpBuffer

);

此函数无返回值,参数是一个指向名为MEMORYSTATUS的结构的指针。函数的返回信息会被存储在MEMORYSTATUS结构中。

此函数用来替代用来支持16位应用程序的GetFreeSpace函数。

2G以上内存建议使用GlobalMemoryStatusEx函数代替(2~4G需要链接器/LARGEADDRESSAWARE选项,4G以上不支持)

应用程序应该在申请内存前调用此函数以防止影响到其他程序运行。

这个函数的返回值是动态的,并且可能返回相同的值。

关于MEMORYSTATUS结构:

结构定义:

?

1

2

3

4

5

6

7

8

9

10

typedef struct _MEMORYSTATUS { // mst

DWORD dwLength; // sizeof(MEMORYSTATUS)

DWORD dwMemoryLoad; // percent of memory in use

DWORD dwTotalPhys; // bytes of physical memory

DWORD dwAvailPhys; // free physical memory bytes

DWORD dwTotalPageFile; // bytes of paging file

DWORD dwAvailPageFile; // free bytes of paging file

DWORD dwTotalVirtual; // user bytes of address space

DWORD dwAvailVirtual; // free user bytes

} MEMORYSTATUS, *LPMEMORYSTATUS;

结构成员的含义:

dwLength

MEMORYSTATUS结构的大小,在调GlobalMemoryStatus函数前用sizeof()函数求得,用来供函数检测结构的版本。

dwMemoryLoad

返回一个介于0~100之间的值,用来指示当前系统内存的使用率。

dwTotalPhys

返回总的物理内存大小,以字节(byte)为单位。

dwAvailPhys

返回可用的物理内存大小,以字节(byte)为单位。

dwTotalPageFile

显示可以存在页面文件中的字节数。注意这个数值并不表示在页面文件磁盘上的真实物理大小。

dwAvailPageFile

返回可用的页面文件大小,以字节(byte)为单位。

dwTotalVirtual

返回调用进程的用户模式部分的全部可用虚拟地址空间,以字节(byte)为单位。

dwAvailVirtual

返回调用进程的用户模式部分的实际自由可用的虚拟地址空间,以字节(byte)为单位。

MEMORYSTATUS结构,

结构的定义如下:

?

1

2

3

4

5

6

7

8

9

10

MEMORYSTATUS STRUCT

dwLength            DWORD      ?     ;本结构的长度

dwMemoryLoad      DWORD      ?     ;已用内存的百分比

dwTotalPhys       DWORD      ?     ;物理内存总量

dwAvailPhys       DWORD      ?     ;可用物理内存

dwTotalPageFile   DWORD      ?     ;交换文件总的大小

dwAvailPageFile   DWORD      ?     ;交换文件中空闲部分大小

dwTotalVirtual    DWORD      ?     ;用户可用的地址空间

dwAvailVirtual    DWORD      ?     ;当前空闲的地址空间

MEMORYSTATUS ENDS

 

转载地址:http://stackoverflow.com/questions/63166/how-to-determine-cpu-and-memory-consumption-from-inside-a-process

<think>嗯,用户遇到了一个错误:“Unable to determine period from endog”,想要解决这个问题。我需要先理解这个错误通常出现在什么情况下。根据引用中的信息,这个错误可能与周期分量的设置有关,比如是否启用了阻尼(damped)。首先,我应该回忆一下时间序列分析中的周期检测问题。 这个错误可能出现在使用某些统计库的时候,比如Python的statsmodels,尤其是在处理季节性分解或ARIMA模型时。当模型需要确定数据的周期性(period)但无法从输入数据endog中自动检测到周期时,就会抛出这个错误。endog通常是 endogenous variable(内生变量)的缩写,也就是时间序列数据本身。 接下来,我需要考虑用户可能的数据情况。例如,用户的数据可能没有足够明显的周期性,或者数据的时间频率信息没有被正确识别。比如,如果数据是按月收集的,但没有明确设置频率,模型可能无法自动推断出周期为12个月。或者,数据可能包含缺失值,导致无法正确推断周期。 然后,解决方案可能包括手动指定周期参数。比如在seasonal_decompose函数中,设置period参数。或者在创建时间序列模型时,明确指定seasonal_order中的周期值。另外,检查数据是否有足够的长度,比如至少包含两个完整的周期,否则模型无法确定周期。 另外,数据预处理也很重要。比如确保数据的时间索引正确,填充缺失值,或者调整数据频率。如果数据本身确实没有周期性,可能需要使用非周期性的模型,或者调整模型参数来禁用周期性组件。 用户提供的引用中提到周期分量的阻尼选项默认是False,这可能与模型配置有关。比如在STL分解或状态空间模型中,是否启用了阻尼周期分量可能会影响周期检测。不过这个具体的配置可能需要结合具体代码来分析。 总结可能的解决步骤: 1. 检查数据是否有足够的周期样本。 2. 手动指定周期参数。 3. 确保数据时间频率正确设置。 4. 处理数据中的缺失值。 5. 调整模型参数,禁用周期组件或使用替代方法。 然后,我需要验证这些步骤是否合理。例如,如果用户的数据是月度数据,但未设置频率,使用pandas的asfreq或infer_freq可能会有帮助。或者在调用分解函数时显式传递period参数。此外,如果数据太短,比如只有一年的月度数据,则可能不足以检测周期,需要用户提供更长的数据或手动指定。 最后,还需要考虑用户可能忽略的其他因素,比如数据是否为常规时间序列,是否存在重复的时间戳,或者数据格式是否正确。例如,endog是否是一个正确的时间序列对象,而不仅仅是数组。</think>### 错误分析 错误 `Unable to determine period from endog` 通常出现在时间序列模型中(如 `statsmodels` 的 `STL` 分解或 `ARIMA` 模型),表明模型无法从输入数据 `endog` 中自动推断出周期性。常见原因包括: 1. **数据未明确设置时间频率**:若数据未标注时间索引(如 `pandas` 的 `DatetimeIndex` 缺失频率),模型无法推断周期[^1]。 2. **数据长度不足**:数据需包含至少两个完整周期(例如月度数据至少24个月)。 3. **周期性不显著**:数据噪声过大会干扰周期检测。 --- ### 解决方案 #### 1. 手动指定周期参数 在调用模型时直接定义 `period` 参数(例如月度数据周期为12): ```python from statsmodels.tsa.seasonal import STL result = STL(endog, period=12).fit() # 强制指定周期 ``` #### 2. 修复时间序列频率 确保数据时间索引包含频率信息: ```python import pandas as pd # 若原始数据未设置频率,需手动推断或指定 ts = pd.Series(data, index=pd.date_range(start="2020-01", periods=len(data), freq="M")) ``` #### 3. 验证数据长度 若数据长度不足,需扩展数据或调整周期参数: ```python if len(endog) < 2 * period: # 若数据少于两倍周期长度 raise ValueError("数据需包含至少两个完整周期") ``` #### 4. 禁用周期组件(若无需周期性) 对于某些模型(如 `ExponentialSmoothing`),可关闭周期检测: ```python model = ExponentialSmoothing(endog, seasonal=None).fit() # 禁用季节项 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值