source: XIOS3/trunk/src/mem_checker.cpp @ 2535

Last change on this file since 2535 was 2535, checked in by jderouillat, 11 months ago

Backport [2448,2503,2516], ocean component in generic_testcase, memory_report option and nvertex name

  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 6.5 KB
Line 
1#include "mem_checker.hpp"
2#include "cxios.hpp"
3#include "mpi.hpp"
4#include <string>
5#include <map>
6#include <iostream>
7#include <sstream>
8
9#include <fcntl.h>
10#include <iomanip>
11#include <unistd.h>
12#include <cstring>
13
14namespace xios
15{
16  CMemChecker CMemChecker::dummy_("") ;
17  std::map<std::string,CMemChecker> CMemChecker::allMemChecker_;
18  bool CMemChecker::enabled_=true;
19  bool CMemChecker::first_=true;
20  double CMemChecker::vsize_init_=0;
21  double CMemChecker::rss_init_=0;
22  double CMemChecker::vmhwm_init_=0;
23  double CMemChecker::time_init_=0;
24  std::ofstream CMemChecker::fout_;
25  int CMemChecker::flush_counter_=1;
26 
27  CMemChecker::CMemChecker(const std::string& name) : name_(name)
28  { 
29    if (first_) check() ;
30    reset();
31  }
32
33  void CMemChecker::check(void)
34  {
35    std::ifstream statStream("/proc/self/stat",std::ios_base::in);
36    enabled_ &= statStream.good() ;
37    first_=false ;
38  }
39 
40  // Return vector of memories amount :
41  //   - vector[0] : virtual memory (vsize) from /proc/self/stat
42  //   - vector[1] : resident set size (rss) from /proc/self/stat
43  std::vector<double> CMemChecker::getMem(void)
44  {
45    std::vector<double> memories(0);
46    if ( !CXios::reportMemory ) return memories ;
47    memories.clear();
48   
49    if (first_) check() ;
50    if (!enabled_) return memories;
51    std::ifstream statStream("/proc/self/stat",std::ios_base::in);
52    std::string dummy ;
53    for(int i=1;i<=22;i++) statStream>>dummy ;
54    unsigned long vsize; 
55    statStream>>vsize ;
56    memories.push_back(vsize);
57    unsigned long rss;
58    statStream>>rss ;
59    memories.push_back(rss*4096);
60    return memories ;
61  }
62 
63  // Return vector of memories amount, register values (see _init) as first call as reference :
64  //   - vector[0] : virtual memory (vsize) from /proc/self/stat
65  //   - vector[1] : resident set size (rss) from /proc/self/stat
66  //   - vector[2] : Peak resident set size (VmHWM) from /proc/self/status
67  std::vector<double> CMemChecker::getMemories(void)
68  {
69    std::vector<double> memories;
70
71    if (first_) check() ;
72    if (!enabled_) return memories;
73    std::ifstream statStream("/proc/self/stat",std::ios_base::in);
74    std::string dummy ;
75    for(int i=1;i<=22;i++) statStream>>dummy ;
76
77    // 1 - Virtual
78    unsigned long vsize; 
79    statStream>>vsize ;
80    if (vsize_init_==0) {
81      vsize_init_ = vsize;
82      time_init_=MPI_Wtime();
83    }
84    vsize -= vsize_init_;
85    memories.push_back(vsize);
86
87    // 2 - RSS
88    unsigned long rss;
89    statStream>>rss ;
90    if (rss_init_==0) {
91      rss_init_ = rss;
92    }
93    rss -= rss_init_;
94    rss *= 4096; //getconf("PAGE_SIZE");   
95    memories.push_back(rss);
96
97    // 3 - Peak
98    char sbuf[1024];
99    std::ifstream file( "/proc/self/status" );
100    if( file.fail() ) {
101      return memories;
102    }
103    int fd = open( "/proc/self/status", O_RDONLY, 0 );
104    int num_read=read( fd, sbuf, ( sizeof sbuf )-1 );
105    close( fd );
106    if( !num_read ) {
107      return memories;             
108    }
109    // Peak resident set size
110    char *S=strstr( sbuf, "VmHWM:" )+6;
111    double vmhwm = ( int )atoi( S );
112    if (vmhwm_init_==0) {
113      vmhwm_init_ = vmhwm;
114    }
115    vmhwm -= vmhwm_init_;
116    memories.push_back(vmhwm);
117   
118    return memories;
119  }
120 
121  void CMemChecker::logMem( std::string id, bool finalizeLog )
122  {
123    if ( !CXios::logMemory ) return ;
124
125    int rk = 0;
126    MPI_Comm_rank( MPI_COMM_WORLD, &rk );
127    std::string logName("xios_memory_"+std::to_string(rk)+".csv");
128    vector<double> mem = getMemories();
129    if (!mem[0]) {
130      fout_.open( logName );
131      fout_ << "time,event,vsize,rss,VmHWM" << std::endl;
132    }
133
134    fout_.precision(4);
135    // Time format : YYYY-MM-DD HH:MM:SS.XXX -> seconds * 1000.
136    fout_ << (MPI_Wtime()-time_init_) << "," << id
137          << "," << mem[0]/1024./1024.
138          << "," << mem[1]/1024./1024.
139          << "," << mem[2]/1024.
140          << std::endl;
141
142    if ((MPI_Wtime()-time_init_)>flush_counter_*600.)
143    {
144      fout_.flush();
145      flush_counter_++;
146    }
147   
148    if (finalizeLog)
149    {
150      fout_.close();
151    }
152  }
153
154 
155  void CMemChecker::suspend(void)
156  {
157    if (first_) check() ;
158    if (!enabled_) return ;
159    if (!suspended_)
160    {
161      vector<double> mem = getMem();
162      cumulatedMem_.resize( mem.size() );
163      for (int i=0;i<mem.size() ; i++)
164      {
165        cumulatedMem_[i] += mem[i] - lastMem_[i];
166      }
167    }
168    suspended_ = true;
169  }
170 
171  void CMemChecker::resume(void)
172  {
173    if (first_) check() ;
174    if (!enabled_) return ;
175    if (suspended_)
176    {
177      vector<double> mem = getMem();
178      lastMem_.resize( mem.size() );
179      for (int i=0;i<mem.size() ; i++)
180      {
181        lastMem_[i] = mem[i];
182      }
183    }
184    suspended_ = false;
185  }
186
187  void CMemChecker::reset(void)
188  {
189    if (first_) check() ;
190    if (!enabled_) return ;
191    cumulatedMem_.clear();
192    suspended_ = true;
193  }
194 
195  std::vector<double> CMemChecker::getCumulatedMem(void)
196  {
197    std::vector<double> memories;
198    memories.clear();
199    if (first_) check() ;
200    if (!enabled_) return memories;
201    return cumulatedMem_;
202  }
203 
204  CMemChecker& CMemChecker::get(const std::string name)
205  {
206    if (first_) check() ;
207    if (!enabled_) return dummy_ ;
208    else
209    {
210      std::map<std::string,CMemChecker>::iterator it = allMemChecker_.find(name);
211      if (it == allMemChecker_.end())
212        it = allMemChecker_.insert(std::make_pair(name, CMemChecker(name))).first;
213      return it->second;
214    }
215  }
216
217  std::string CMemChecker::getAllCumulatedMem(void)
218  {
219    if (first_) check() ;
220    if (!enabled_) return std::string(" MemChecker : memory consumption report not available") ; 
221    std::ostringstream strOut ;
222    const double Kb=1024 ;
223    const double Mb=Kb*1024 ;
224    const double Gb=Mb*1024 ;
225    const double Tb=Gb*1024 ;
226    for(std::map<std::string,CMemChecker>::iterator it=allMemChecker_.begin();it!=allMemChecker_.end();++it)
227    { 
228      vector<double> mem=it->second.getCumulatedMem() ;
229      if (mem.size()>0)
230      {
231        strOut<<"MemChecker : "<<it->first<<"    -->   consumed memory : " ;     
232        if ((fabs(mem[0])>=Tb)||(fabs(mem[1])>=Tb)) strOut<< mem[0] / Tb<<" Tb - "<<mem[1] / Tb<<" Tb"<<std::endl ;
233        else if ((fabs(mem[0])>=Gb)||(fabs(mem[1])>=Gb)) strOut<< mem[0] / Gb<<" Gb - "<<mem[1] / Gb<<" Gb"<<std::endl ;
234        else if ((fabs(mem[0])>=Mb)||(fabs(mem[1])>=Mb)) strOut<< mem[0] / Mb<<" Mb - "<<mem[1] / Mb<<" Mb"<<std::endl ;
235        else if ((fabs(mem[0])>=Kb)||(fabs(mem[1])>=Kb)) strOut<< mem[0] / Kb<<" Kb - "<<mem[1] / Kb<<" Kb"<<std::endl ;
236        else strOut<< mem[0] <<" bytes - "<<mem[1] <<" bytes"<<std::endl ;
237      }
238    }
239    return strOut.str() ;
240  }
241}
Note: See TracBrowser for help on using the repository browser.