如何从C++进程内部测量CPU和内存:完整指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

性能盲区:为什么你的进程不知道自己消耗了多少资源?

\n\n

想象一下:你编写了一个复杂的C++应用程序,它运行正常,但开始变慢。你运行top、htop或任务管理器——发现你的进程消耗了90%的CPU或数GB内存。但如何让进程本身意识到这一点,并例如动态降低负载或清除缓存?

\n\n

这不仅仅是学术兴趣。在生产环境中,在没有GUI的服务器上,你不能依赖外部工具。程序需要自我监控。这正是Stack Overflow上一个热门问题所解决的:"如何从进程内部确定CPU和内存消耗"。让我们用C++的真实示例来解析它。

\n\n

跨平台困境:Linux vs Windows

\n\n

操作系统以不同方式提供对进程统计信息的访问。Linux底层是虚拟文件系统/proc,而Windows使用Win32 API。我们将编写一个通用类,在两个平台上都能工作。

\n\n

我们将获取的主要指标:

\n
    \n
  • CPU使用率(百分比或核心份额)
  • \n
  • 物理内存(RSS)——实际占用的RAM
  • \n
  • 虚拟内存(VSZ)——地址空间总量
  • \n
\n\n

在Linux上读取CPU:/proc/self/stat的魔力

\n\n

要获取进程的CPU时间,我们读取/proc/self/stat文件。它包含数十个字段,我们感兴趣的是第13-16字段(utime, stime, cutime, cstime)——以滴答(jiffies)为单位的时间。要转换为百分比,需要知道滴答频率(sysconf(_SC_CLK_TCK))和系统总运行时间。

\n\n
#ifdef __linux__\n#include <unistd.h>\n#include <fstream>\n#include <sstream>\n#include <string>\n#include <vector>\n\ndouble getCpuUsageLinux() {\n    static unsigned long long prevTotal = 0, prevIdle = 0;\n    static double prevProcessTicks = 0;\n    static bool first = true;\n\n    // 进程时间\n    std::ifstream procStat("/proc/self/stat");\n    std::string line;\n    std::getline(procStat, line);\n    std::istringstream iss(line);\n    std::vector<std::string> fields;\n    std::string field;\n    while (iss >> field) fields.push_back(field);\n\n    unsigned long utime = std::stoul(fields[13]);\n    unsigned long stime = std::stoul(fields[14]);\n    unsigned long cutime = std::stoul(fields[15]);\n    unsigned long cstime = std::stoul(fields[16]);\n    double processTicks = utime + stime + cutime + cstime;\n\n    // 系统时间\n    std::ifstream statFile("/proc/stat");\n    std::getline(statFile, line);\n    statFile.close();\n    std::istringstream iss2(line);\n    std::string cpuLabel;\n    iss2 >> cpuLabel;\n    unsigned long long user, nice, system, idle, iowait, irq, softirq, steal;\n    iss2 >> user >> nice >> system >> idle >> iowait >> irq >> softirq >> steal;\n    unsigned long long total = user + nice + system + idle + iowait + irq + softirq + steal;\n\n    if (first) {\n        prevTotal = total;\n        prevIdle = idle;\n        prevProcessTicks = processTicks;\n        first = false;\n        return 0.0;\n    }\n\n    unsigned long long totalDelta = total - prevTotal;\n    double processDelta = processTicks - prevProcessTicks;\n    double cpuPercent = (processDelta / totalDelta) * 100.0;\n\n    prevTotal = total;\n    prevIdle = idle;\n    prevProcessTicks = processTicks;\n\n    return cpuPercent;\n}\n#endif\n
\n\n

这段代码计算自首次调用以来进程占用的CPU百分比。注意:我们取两次测量之间的差值——这是保证精度的标准方法。

\n\n

在Linux上读取内存:RSS和VSZ

\n\n

对于内存,我们读取/proc/self/status。我们感兴趣的行是

博客

书籍推荐