Zona ciega de rendimiento: ¿por qué su proceso no sabe cuánto consume?
\n\nImagine: ha escrito una aplicación compleja en C++, funciona, pero empieza a ralentizarse. Ejecuta top, htop o el administrador de tareas — y ve que su proceso consume el 90% de CPU o gigabytes de memoria. Pero, ¿cómo hacer que el propio proceso tome conciencia de esto y, por ejemplo, reduzca dinámicamente la carga o libere la caché?
Esto no es solo un interés académico. En un entorno de producción, en servidores sin GUI, no puede depender de utilidades externas. Es necesario que el programa se supervise a sí mismo. Precisamente este problema resuelve la popular pregunta en Stack Overflow: "How to determine CPU and memory consumption from inside a process". Analicémosla con ejemplos reales en C++.
\n\nEl dilema multiplataforma: Linux vs Windows
\n\nLos sistemas operativos proporcionan acceso a las estadísticas de procesos de diferentes maneras. Bajo el capó de Linux se encuentra el sistema de archivos virtual /proc, mientras que Windows utiliza la API Win32. Escribiremos una clase universal que funcione en ambas plataformas.
Las métricas principales que obtendremos:
\n- \n
- Uso de CPU (en porcentaje o fracciones de núcleo) \n
- Memoria física (RSS) — RAM realmente ocupada \n
- Memoria virtual (VSZ) — volumen total del espacio de direcciones \n
Lectura de CPU en Linux: la magia de /proc/self/stat
\n\nPara obtener el tiempo de CPU del proceso, leemos el archivo /proc/self/stat. Contiene decenas de campos, nos interesan los campos 13-16 (utime, stime, cutime, cstime) — tiempo en ticks (jiffies). Para convertir a porcentaje, necesitamos conocer la frecuencia de ticks (sysconf(_SC_CLK_TCK)) y el tiempo total de funcionamiento del 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 // Tiempo del proceso\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 // Tiempo del 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 el porcentaje de CPU ocupado por el proceso desde la primera llamada. Tenga en cuenta: tomamos la diferencia entre dos mediciones — este es el enfoque estándar para la precisión.
\n\nMemoria en Linux: RSS y VSZ
\n\nPara la memoria, leemos /proc/self/status. Nos interesan las líneas