Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

อ่าน Memory Usage ใน Linux ด้วย C++: อ่าน /proc/self/stat

ใน Linux ข้อมูล Process Memory อยู่ใน Virtual Filesystem /proc/<PID>/stat สำหรับ Process ตัวเองใช้ /proc/self/stat ไฟล์นี้มีข้อมูลมากกว่า 50 Fields เราสนใจ 2 Fields:

  • Vsize (Virtual Memory Size): Field 23 - Virtual Address Space ทั้งหมด (Bytes)
  • RSS (Resident Set Size): Field 24 - Physical RAM ที่ใช้จริง (Pages)

โค้ดอ่าน Memory Usage

#include <iostream>
#include <fstream>
#include <string>
#include <unistd.h>  // sysconf

void get_memory_usage(double& vm_usage_kb, double& rss_kb) {
    vm_usage_kb = 0.0;
    rss_kb = 0.0;

    std::ifstream stat_stream("/proc/self/stat");
    if (!stat_stream) return;

    // อ่าน Fields 1-22 (Skip ด้วย Dummy Variables)
    std::string pid, comm, state, ppid, pgrp, session, tty_nr;
    std::string tpgid, flags, minflt, cminflt, majflt, cmajflt;
    std::string utime, stime, cutime, cstime, priority, nice;
    std::string itrealvalue, starttime;
    
    unsigned long vsize; // Field 23: Virtual Memory (bytes)
    long rss;            // Field 24: Resident Set Size (pages)

    stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr
                 >> tpgid >> flags >> minflt >> cminflt >> majflt >> cmajflt
                 >> utime >> stime >> cutime >> cstime >> priority >> nice
                 >> itrealvalue >> starttime >> vsize >> rss;

    stat_stream.close();

    long page_size_kb = sysconf(_SC_PAGESIZE) / 1024; // KB per Page (มัก 4 KB)
    vm_usage_kb = vsize / 1024.0;      // Bytes -> KB
    rss_kb = rss * page_size_kb;       // Pages -> KB
}

int main() {
    double vm, rss;
    get_memory_usage(vm, rss);
    std::cout << "Virtual Memory: " << vm << " KB\n";
    std::cout << "Resident Set Size: " << rss << " KB\n";
    return 0;
}

ผลลัพธ์ตัวอย่าง

Virtual Memory: 13272 KB
Resident Set Size: 1548 KB

ความหมายของ Metrics

  • Virtual Memory (Vsize): Address Space ที่ Process จองไว้ (รวม Code, Data, Heap, Stack, Shared Libs, Memory Mapped Files) - อาจใหญ่กว่า RAM จริง
  • RSS: Physical RAM ที่ Process ใช้จริง (ไม่รวม Swapped Out, Shared Memory นับซ้ำได้)
  • PSS (Proportional Set Size): RSS ที่แบ่งน้ำหนัก Shared Memory (อ่านจาก /proc/<pid>/smaps)

ทางเลือกอื่น

  1. getrusage(RUSAGE_SELF, &usage) - POSIX Standard (ให้ maxrss ใน KB)
  2. /proc/self/status - Parse ง่ายกว่า (Key: Value Format)
  3. mallinfo() / malloc_info() - Heap Allocator Stats (Glibc)

ตัวอย่างด้วย /proc/self/status (ง่ายกว่า)

void get_mem_simple(double& vm_kb, double& rss_kb) {
    std::ifstream status("/proc/self/status");
    std::string line;
    while (std::getline(status, line)) {
        if (line.rfind("VmSize:", 0) == 0) 
            vm_kb = std::stod(line.substr(7));
        else if (line.rfind("VmRSS:", 0) == 0)
            rss_kb = std::stod(line.substr(6));
    }
}

สรุป

การอ่าน /proc/self/stat ให้ Low-level Control สูงสุด แต่ Parse ยุ่งยาก /proc/self/status ใช้ง่ายกว่า getrusage() เป็น Portable POSIX เลือกตามความต้องการ