#ifndef _MEM_MONITOR_H_ #define _MEM_MONITOR_H_ #include #include #include #include #include #include // 获取当前进程 RSS (物理内存) 使用量,单位 MB static inline long getRSS_KB() { long rss = 0; FILE *fp = fopen("/proc/self/status", "r"); if (!fp) return -1; char line[256]; while (fgets(line, sizeof(line), fp)) { if (strncmp(line, "VmRSS:", 6) == 0) { // 格式: "VmRSS: 12345 kB" const char *p = line + 6; while (*p == ' ' || *p == '\t') p++; rss = atol(p); break; } } fclose(fp); return rss; } // 获取当前进程内存使用,打印格式化日志 static inline void printMemUsage(const char *tag, const char *extra) { long rss = getRSS_KB(); struct rusage usage; getrusage(RUSAGE_SELF, &usage); printf("[MEM] %-30s | VmRSS: %6ld MB | maxRSS: %6ld MB | %s\n", tag, rss / 1024, usage.ru_maxrss / 1024, extra ? extra : ""); } // 获取产品检测 pipeline 队列深度信息快照 #define MEM_LOG(tag, fmt, ...) \ do { \ long _rss = getRSS_KB(); \ printf("[MEM] %-30s | VmRSS: %6ld MB | " fmt "\n", tag, _rss / 1024, ##__VA_ARGS__); \ } while(0) // 获取 GPU 显存使用情况(通过 nvidia-smi),返回所有 GPU 累加的已用/总量,单位 MB // 成功返回 0,失败返回 -1(此时 usedMB/totalMB 置为 -1) static inline int getGPUMemInfo(long &usedMB, long &totalMB) { usedMB = -1; totalMB = -1; FILE *fp = popen("nvidia-smi --query-gpu=memory.used,memory.total --format=csv,noheader,nounits 2>/dev/null", "r"); if (!fp) { return -1; } char line[256]; long used = 0; long total = 0; int n = 0; while (fgets(line, sizeof(line), fp)) { long u = 0; long t = 0; if (sscanf(line, "%ld, %ld", &u, &t) == 2) { used += u; total += t; n++; } } pclose(fp); if (n == 0) { return -1; } usedMB = used; totalMB = total; return 0; } // 获取系统内存信息(/proc/meminfo),单位 KB // 成功返回 0,失败返回 -1(此时各值置为 -1) static inline int getSystemMemInfo(long &totalKB, long &freeKB, long &availableKB) { totalKB = -1; freeKB = -1; availableKB = -1; FILE *fp = fopen("/proc/meminfo", "r"); if (!fp) { return -1; } char line[256]; while (fgets(line, sizeof(line), fp)) { long val = -1; if (sscanf(line, "MemTotal: %ld kB", &val) == 1) { totalKB = val; } else if (sscanf(line, "MemFree: %ld kB", &val) == 1) { freeKB = val; } else if (sscanf(line, "MemAvailable: %ld kB", &val) == 1) { availableKB = val; } } fclose(fp); return 0; } // 系统 CPU 时间快照(/proc/stat 第一行 cpu 累计值),用于两次采样计算 CPU 使用率 struct CPUStat { unsigned long long user; unsigned long long nice; unsigned long long system; unsigned long long idle; unsigned long long iowait; unsigned long long irq; unsigned long long softirq; unsigned long long steal; CPUStat() { user = nice = system = idle = iowait = irq = softirq = steal = 0; } unsigned long long total() const { return user + nice + system + idle + iowait + irq + softirq + steal; } unsigned long long idleTotal() const { return idle + iowait; } }; // 读取系统 CPU 时间快照,成功返回 0,失败返回 -1 static inline int getSystemCPUStat(CPUStat &stat) { FILE *fp = fopen("/proc/stat", "r"); if (!fp) { return -1; } char line[256]; int ret = -1; if (fgets(line, sizeof(line), fp)) { // 格式: cpu user nice system idle iowait irq softirq steal guest guest_nice if (sscanf(line, "cpu %llu %llu %llu %llu %llu %llu %llu %llu", &stat.user, &stat.nice, &stat.system, &stat.idle, &stat.iowait, &stat.irq, &stat.softirq, &stat.steal) >= 4) { ret = 0; } } fclose(fp); return ret; } // 进程累计消耗的 CPU 时间(用户态 + 内核态),单位秒 static inline double cpuTimeSec(const struct rusage &usage) { return (double)usage.ru_utime.tv_sec + (double)usage.ru_utime.tv_usec / 1e6 + (double)usage.ru_stime.tv_sec + (double)usage.ru_stime.tv_usec / 1e6; } #endif // _MEM_MONITOR_H_