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

Last change on this file since 2418 was 2418, checked in by jderouillat, 21 months ago

Integrates a system to log the memory consumption from XIOS init to XIOS finalize, and a HTML webpage to visualize it. The API to use it from models is available too.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 4.8 KB
Line 
1#include "mem_checker.hpp"
2#include "mpi.hpp"
3#include <string>
4#include <map>
5#include <iostream>
6#include <sstream>
7#include <fstream>
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::time_init_=0;
22
23  CMemChecker::CMemChecker(const std::string& name) : name_(name) 
24  { 
25    if (first_) check() ;
26    reset();
27  }
28
29  void CMemChecker::check(void)
30  {
31    std::ifstream statStream("/proc/self/stat",std::ios_base::in);
32    enabled_ &= statStream.good() ;
33    first_=false ;
34  }
35  double CMemChecker::getMem(void)
36  {
37    if (first_) check() ;
38    if (!enabled_) return 0;
39    std::ifstream statStream("/proc/self/stat",std::ios_base::in);
40    std::string dummy ;
41    for(int i=1;i<=22;i++) statStream>>dummy ;
42    unsigned long vsize; 
43    statStream>>vsize ;
44    return vsize ;
45  }
46  double CMemChecker::getMemRSS(void)
47  {
48    //sleep( 1 ) ;
49    if (first_) check() ;
50    if (!enabled_) return 0;
51    std::ifstream statStream("/proc/self/stat",std::ios_base::in);
52    std::string dummy ;
53    for(int i=1;i<=23;i++) statStream>>dummy ;
54    double vsize; 
55    statStream>>vsize ;
56    if (vsize_init_==0) {
57      vsize_init_ = vsize;
58      time_init_=MPI_Wtime();
59    }
60    vsize -= vsize_init_;
61    vsize *= 4096; //getconf("PAGE_SIZE");
62    return vsize ;
63  }
64  void CMemChecker::logMem( std::string id, bool finalizeLog )
65  {
66    // function get_xios_mem_data() {
67    //   return [
68    //        ...
69    //        [ "2000-01-01 01:00:10.XXX", "XIOS close context def", 1000],
70    //        [ "2000-01-01 01:00:11.XXX", "update timestep"       , 1000],
71    //        [ "2000-01-01 01:00:15.XXX", "send field"            , 2000],
72    //        ...
73    //   ];
74    // }
75   
76    std::ofstream fout;
77    int rk = 0;
78    MPI_Comm_rank( MPI_COMM_WORLD, &rk );
79    std::string logName("mem_"+std::to_string(rk)+".js");
80    double mem = getMemRSS();
81    if (!mem) {
82      fout.open( logName );
83      fout << "function get_xios_mem_data() {" << std::endl;
84      fout << "  return [" << std::endl;
85    }
86    else
87    {
88      fout.open( logName, std::ios_base::app );
89    }
90
91    // Time format : YYYY-MM-DD HH:MM:SS.XXX -> seconds * 1000.
92    fout << "        [ " << (MPI_Wtime()-time_init_)*1000. << ", \"" << id << "\"," << mem/1000000. << "]," << std::endl;
93
94    if (finalizeLog)
95    {
96      fout << "  ];" << std::endl;
97      fout << "}" << std::endl;
98    }
99    fout.close();
100  }
101
102 
103  void CMemChecker::suspend(void)
104  {
105    if (first_) check() ;
106    if (!enabled_) return ;
107    if (!suspended_) cumulatedMem_ += getMem() - lastMem_;
108    suspended_ = true;
109  }
110 
111  void CMemChecker::resume(void)
112  {
113    if (first_) check() ;
114    if (!enabled_) return ;
115    if (suspended_) lastMem_ = getMem();
116    suspended_ = false;
117  }
118
119  void CMemChecker::suspendRSS(void)
120  {
121    if (first_) check() ;
122    if (!enabled_) return ;
123    if (!suspended_) cumulatedMem_ += getMemRSS() - lastMem_;
124    suspended_ = true;
125  }
126 
127  void CMemChecker::resumeRSS(void)
128  {
129    if (first_) check() ;
130    if (!enabled_) return ;
131    if (suspended_) lastMem_ = getMemRSS();
132    suspended_ = false;
133  }
134 
135
136  void CMemChecker::reset(void)
137  {
138    if (first_) check() ;
139    if (!enabled_) return ;
140    cumulatedMem_ = 0.;
141    suspended_ = true;
142  }
143 
144  double CMemChecker::getCumulatedMem(void)
145  {
146    if (first_) check() ;
147    if (!enabled_) return 0;
148    return cumulatedMem_;
149  }
150 
151  CMemChecker& CMemChecker::get(const std::string name)
152  {
153    if (first_) check() ;
154    if (!enabled_) return dummy_ ;
155    else
156    {
157      std::map<std::string,CMemChecker>::iterator it = allMemChecker_.find(name);
158      if (it == allMemChecker_.end())
159        it = allMemChecker_.insert(std::make_pair(name, CMemChecker(name))).first;
160      return it->second;
161    }
162  }
163
164  std::string CMemChecker::getAllCumulatedMem(void)
165  {
166    if (first_) check() ;
167    if (!enabled_) return std::string(" MemChecker : memory consumption report not available") ; 
168    std::ostringstream strOut ;
169    const double Kb=1024 ;
170    const double Mb=Kb*1024 ;
171    const double Gb=Mb*1024 ;
172    const double Tb=Gb*1024 ;
173    for(std::map<std::string,CMemChecker>::iterator it=allMemChecker_.begin();it!=allMemChecker_.end();++it)
174    { 
175      strOut<<"MemChecker : "<<it->first<<"    -->   consumed memory : " ;
176      double mem=it->second.getCumulatedMem() ;
177      if (mem>=Tb) strOut<< mem / Tb<<" Tb"<<std::endl ;
178      else if (mem>=Gb) strOut<< mem / Gb<<" Gb"<<std::endl ;
179      else if (mem>=Mb) strOut<< mem / Mb<<" Mb"<<std::endl ;
180      else if (mem>=Kb) strOut<< mem / Kb<<" Kb"<<std::endl ;
181      else strOut<< mem <<" bytes"<<std::endl ;
182    }
183    return strOut.str() ;
184  }
185}
Note: See TracBrowser for help on using the repository browser.