性能盲区:为什么你的进程不知道自己消耗了多少资源?
\n\n想象一下:你编写了一个复杂的C++应用程序,它运行正常,但开始变慢。你运行top、htop或任务管理器——发现你的进程消耗了90%的CPU或数GB内存。但如何让进程本身意识到这一点,并例如动态降低负载或清除缓存?
这不仅仅是学术兴趣。在生产环境中,在没有GUI的服务器上,你不能依赖外部工具。程序需要自我监控。这正是Stack Overflow上一个热门问题所解决的:"如何从进程内部确定CPU和内存消耗"。让我们用C++的真实示例来解析它。
\n\n跨平台困境:Linux vs Windows
\n\n操作系统以不同方式提供对进程统计信息的访问。Linux底层是虚拟文件系统/proc,而Windows使用Win32 API。我们将编写一个通用类,在两个平台上都能工作。
我们将获取的主要指标:
\n- \n
- CPU使用率(百分比或核心份额) \n
- 物理内存(RSS)——实际占用的RAM \n
- 虚拟内存(VSZ)——地址空间总量 \n
在Linux上读取CPU:/proc/self/stat的魔力
\n\n要获取进程的CPU时间,我们读取/proc/self/stat文件。它包含数十个字段,我们感兴趣的是第13-16字段(utime, stime, cutime, cstime)——以滴答(jiffies)为单位的时间。要转换为百分比,需要知道滴答频率(sysconf(_SC_CLK_TCK))和系统总运行时间。
#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。我们感兴趣的行是