查看内存工具

进程在heap分配的内存在VSS中有体现,分为shared和private,特别是private基本上和进程申请的内存相当。

/proc/pid/smaps中记录了进程的内存信息,写了一个c++程序来打印内存。

[winlin@dev6 utest]$ ./memview summary 28618
VMSIZE:      42240 KB
RSS:          1800 KB total
              1352 KB shared
               396 KB private clean
                52 KB private dirty

进程28618占用了约1.8M内存。

同时提供了一个python的辅助工具,能按进程名称显示内存。

[winlin@dev6 utest]$ ./memview.py summary rtmp_server
command: ./memview summary 28618 for rtmp_server
VMSIZE:      42240 KB
RSS:          1800 KB total
              1748 KB shared
                 0 KB private clean
                52 KB private dirty
command: ./memview summary 28619 for rtmp_server
VMSIZE:      42240 KB
RSS:           708 KB total
               652 KB shared
                 0 KB private clean
                56 KB private dirty

/*
compile as isolate program:
    g++ memview.cpp -o memview -g -O0 -D mem_view_self_main

cli usage:
    ./memview [pid]
    pid: the pid of process to view memory. default to memview itself.

api usage:
    MemView(pid).Print();
    pid: 0, self, equals to getpid().
    pid: > 0, get the memory stat of speicifed pid.
    pid: < 0, donot get the memory, use Calc(pid) to stat.
    
# Copyright winlin.
# you can distribute this under the MIT/X11 License
*/
    
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <sstream>
#include <assert.h>
#include <unistd.h>
using namespace std;

class SmapsMemItem
{
public:
    string file;
    double vmsize;
    double rss;
    double pss;
    double shared_clean;
    double shared_dirty;
    double private_clean;
    double private_dirty;
    double reference;
    double swap;
    double kernel_page_size;
    double mmu_page_size;
public:
    SmapsMemItem(){
    }
    virtual ~SmapsMemItem(){
    }
public:
    bool operator > (const SmapsMemItem& o) const{
        // if for private mapping.
        if(pss != 0){
            // first by dirty,
            if(private_dirty > o.private_dirty){
                return true;
            }
            // then by clean
            else if(private_dirty == o.private_dirty && private_clean > o.private_clean){
                return true;
            }
            else{
                return false;
            }
        }
        else{
            if(shared_dirty > o.shared_dirty){
                return true;
            }
            else if(shared_dirty == o.shared_dirty && shared_clean > o.shared_clean){
                return true;
            }
            else{
                return false;
            }
        }
    }
    bool operator < (const SmapsMemItem& o) const{
        return !(*this > o);
    }
public:
    bool Read(istream& fs){
        static char skip[1024];
        
        fs >> skip >> skip >> skip >> skip >> skip >> file;
        if(fs.eof()){
            return false;
        }
        // no file
        if(file == "Size:"){
            file = "";
        }
        else{
            fs >> skip;
        }
        
        fs >> vmsize;
        
        fs >> skip >> skip >> rss;
        
        fs >> skip >> skip >> pss;
        
        fs >> skip >> skip >> shared_clean;
        
        fs >> skip >> skip >> shared_dirty;
        
        fs >> skip >> skip >> private_clean;
        
        fs >> skip >> skip >> private_dirty;
        
        fs >> skip >> skip >> reference;
        
        fs >> skip >> skip >> swap;
        
        fs >> skip >> skip >> kernel_page_size;
        
        fs >> skip >> skip >> mmu_page_size;
        
        fs >> skip;
        
        return true;
    }
    void Print(){
        cout << file 
            << " vm:" << vmsize << " rss:" << rss << " pss:" << pss 
            << " shared_clean:" << shared_clean << " shared_dirty:" << shared_dirty
            << " private_clean:" << private_clean << " private_dirty:" << private_dirty
            << " reference:" << reference << " swap:" << swap
            << " kernel_page_size:" << kernel_page_size << " mmu_page_size:" << mmu_page_size
            << endl;
    }
    void ItemPrint(bool print_private){
        cout << setw(8) << fixed << setfill(' ') << vmsize << " kb"
            << setw(9) << fixed << setfill(' ') << ((print_private)? private_clean : shared_clean) << " kb"
            << setw(9) << fixed << setfill(' ') << ((print_private)? private_dirty : shared_dirty) << " kb"
            << setw(3) << fixed << setfill(' ') << " " << file
            << endl;
    }
};

class MemView
{
private:
    int pid;
private:
    vector<SmapsMemItem> private_items;
    vector<SmapsMemItem> shared_items;
public:
    double vmsize;
    double rss;
    double shared_clean; // rss shared clean
    double shared_dirty; // rss shared dirty
    double private_clean; // rss private clean
    double private_dirty; // rss private dirty
public:
    MemView(int pid = 0);
    virtual ~MemView();
private:
    void Clear();
private:
    bool Read(istream& fs);
public:    
    void Print();
public:
    void PrintSummary();
private:
    void PrintPrivateMappings();
public:
    void Calc(int pid);
};

MemView::MemView(int pid){
    this->pid = pid;
    if(pid >= 0){
        Calc(pid);
    }
}
MemView::~MemView(){
}
void MemView::Clear(){
    vmsize = 0;
    rss = 0;
    shared_clean = 0;
    shared_dirty = 0;
    private_clean = 0;
    private_dirty = 0;
    
    shared_items.clear();
    private_items.clear();
}
bool MemView::Read(istream& fs){
    Clear();
    
    while(!fs.eof()){
        SmapsMemItem o;
        
        if(!o.Read(fs)){
            break;
        }
        
        if(o.pss == 0){
            shared_items.push_back(o);
        }
        else{
            private_items.push_back(o);
        }

        vmsize += o.vmsize;
        rss += o.rss;
        shared_clean += o.shared_clean;
        shared_dirty += o.shared_dirty;
        private_clean += o.private_clean;
        private_dirty += o.private_dirty;
        
        //o->Print();
    }
    
    sort(shared_items.begin(), shared_items.end(), greater<SmapsMemItem>());
    sort(private_items.begin(), private_items.end(), greater<SmapsMemItem>());

    return true;
}  
void MemView::Print(){
    PrintSummary();
    PrintPrivateMappings();
}
void MemView::PrintSummary(){
    cout.precision(0);
    cout << "VMSIZE:" << setw(11) << setfill(' ') << fixed << vmsize << " KB" << endl
        << "RSS:" << setw(14) << setfill(' ') << fixed << rss << " KB total" << endl
        << setw(18) << setfill(' ') << fixed << shared_clean + shared_dirty << " KB shared" << endl
        << setw(18) << setfill(' ') << fixed << private_clean << " KB private clean" << endl
        << setw(18) << setfill(' ') << fixed << private_dirty << " KB private dirty" << endl
        ;
}
void MemView::PrintPrivateMappings(){
    if(private_items.size() == 0){
        return;
    }
    
    cout.precision(0);
    cout << endl
        << "Private Mappings" << endl
        << setw(11) << fixed << setfill(' ') << "vmsize" 
        << setw(12) << fixed << setfill(' ') << "rss clean" 
        << setw(12) << fixed << setfill(' ') << "rss dirty" 
        << setw(3) << fixed << setfill(' ') << " " << "file" 
        << endl;
    
    vector<SmapsMemItem>::iterator ite;
    for(ite = private_items.begin(); ite != private_items.end(); ++ite){
        SmapsMemItem& item = *ite;
        item.ItemPrint(true);
    }
    
    cout << endl
        << "Shared Mappings" << endl
        << setw(11) << fixed << setfill(' ') << "vmsize" 
        << setw(12) << fixed << setfill(' ') << "rss clean" 
        << setw(12) << fixed << setfill(' ') << "rss dirty" 
        << setw(3) << fixed << setfill(' ') << " " << "file" 
        << endl;
    for(ite = shared_items.begin(); ite != shared_items.end(); ++ite){
        SmapsMemItem& item = *ite;
        item.ItemPrint(false);
    }
}
void MemView::Calc(int pid){
    assert(pid >= 0);
    
    int actual_pid = pid;
    if(actual_pid == 0){
        actual_pid = getpid();
    }
    
    stringstream ss;
    ss << "/proc/" << actual_pid << "/smaps";
    string file = ss.str();
    //cout << "stat the file: " << file << endl;

    if(access(file.c_str(), R_OK) != 0){
        cout << "process(#" << pid << ") does not exists! open file " << file << " error!" << endl;
        exit(-1);
    }

    fstream fs(file.c_str(), ios::in);
    
    Read(fs);
    
    fs.close();
}

#ifdef mem_view_self_main
int main(int argc, char** argv){
    int pid = 0x0;
    string mode;
    if(argc <= 2){
        cout << "Usage: " << argv[0] << " <mode> <pid>" << endl
            << "  pid: the pid of process to view memory. 0: self." << endl
            << "  mode: full or summary. full: print all info; summary: print summary only." << endl;
        exit(-1);
    }
    else{
        mode = argv[1];
        pid = atoi(argv[2]);
    }

    assert(pid >= 0);
    if(mode == "full"){
        MemView(pid).Print();
    }
    else{
        MemView(pid).PrintSummary();
    }
    return 0;
}
#endif

#!/usr/bin/python
'''
usage: python memview.py <mode> <key>
mode: full|summary. default is summary.
key: the app name to view memory. default is rtmp_utest

1. compile if memview does not exist:
    g++ memview.cpp -o memview -g -O0 -D mem_view_self_main
2. find the rtmp_utest process and get its memory view:
    ps aux|grep rtmp_utest
    ./memview summary <pid>
'''

import os, sys;

if not os.path.exists("memview"):
    print "compile memview: g++ memview.cpp -o memview -g -O0 -D mem_view_self_main";
    os.system("g++ memview.cpp -o memview -g -O0 -D mem_view_self_main");
    
if not os.path.exists("memview"):
    print "compile memview failed!";
    sys.exit(-1);
    
if len(sys.argv) <= 2:
    print "Usage %s <mode> <process_name>"%(sys.argv[0]);
    print " mode: summary or full.";
    print " process_name: the name of process.";
    print "For example: %s summary rtmp_server"%(sys.argv[0]);
    sys.exit(-1);
mode = sys.argv[1];
key = sys.argv[2];

grep_key = "|grep %s"%(key);
for s in ['_', '-', '.']:
    if s in key:    
        grep_key = " ".join("|grep "+x+" " for x in key.split(s));
        break;
grep_command="ps aux %s"%(grep_key);
p = os.popen(grep_command);
lines = p.readlines();
p.close();

pid = None;
got_one = False;
for line in lines:
    if "sh -c" in line or sys.argv[0] in line:
        continue;
        
    pid = None;
    index = 0;
    while pid is None or len(pid) == 0 or not pid.isdigit():
        pid = line.replace("  ", " ").split(" ")[index];
        index += 1;

    if pid is None:
        print "cannot find process %s"%(key);
        sys.exit(-1);

    if len(pid) <= 0:
        print "cannot find the %s!!!"%(key);
        sys.exit(-1);
        
    got_one = True;
    cmd = "./memview %s %s"%(mode, pid);
    print "command: %s for %s"%(cmd, key);
    os.system(cmd);
    
if not got_one:
    print 'cannot find process %s, grep= " %s "'%(key, grep_command);


你可能感兴趣的:(String,rss,File,command,工具,reference)