Ponto cego de desempenho: por que seu processo não sabe quanto está consumindo?
\n\nImagine: você escreveu uma aplicação complexa em C++, ela funciona, mas começa a ficar lenta. Você executa top, htop ou o gerenciador de tarefas — e vê que seu processo está consumindo 90% da CPU ou gigabytes de memória. Mas como fazer o próprio processo perceber isso e, por exemplo, reduzir dinamicamente a carga ou limpar o cache?
Isso não é apenas interesse acadêmico. Em ambiente de produção, em servidores sem GUI, você não pode depender de utilitários externos. É necessário que o próprio programa monitore a si mesmo. É exatamente esse problema que resolve a pergunta popular no Stack Overflow: "How to determine CPU and memory consumption from inside a process". Vamos analisá-la com exemplos reais em C++.
\n\nDilema multiplataforma: Linux vs Windows
\n\nOs sistemas operacionais fornecem acesso às estatísticas dos processos de maneiras diferentes. Internamente, o Linux usa o sistema de arquivos virtual /proc, enquanto o Windows usa a Win32 API. Escreveremos uma classe universal que funciona em ambas as plataformas.
As principais métricas que vamos obter:
\n- \n
- Uso de CPU (em porcentagem ou fração de núcleo) \n
- Memória física (RSS) — RAM realmente ocupada \n
- Memória virtual (VSZ) — volume total do espaço de endereçamento \n
Lendo CPU no Linux: a magia do /proc/self/stat
\n\nPara obter o tempo de CPU do processo, lemos o arquivo /proc/self/stat. Ele contém dezenas de campos; nos interessam os campos 13-16 (utime, stime, cutime, cstime) — tempo em ticks (jiffies). Para converter em porcentagem, precisamos saber a frequência de ticks (sysconf(_SC_CLK_TCK)) e o tempo total de operação do sistema.
#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 // Tempo do processo\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 // Tempo do sistema\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\nEste código calcula a porcentagem de CPU ocupada pelo processo desde a primeira chamada. Observe: pegamos a diferença entre duas medições — esta é a abordagem padrão para precisão.
\n\nMemória no Linux: RSS e VSZ
\n\nPara memória, lemos /proc/self/status. Nos interessam as linhas