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

Last change on this file since 2425 was 2425, checked in by jderouillat, 19 months ago

Update the memory log system to log virtual memory, resident memory and resident peak memory

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