StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StMemStat.cxx
1 /***************************************************************************
2  *
3  * $Id: StMemStat.cxx,v 1.10 2019/07/22 18:27:12 smirnovd Exp $
4  *
5  ***************************************************************************
6  *
7  * Description:
8  *
9  ***************************************************************************
10  **************************************************************************/
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <math.h>
14 #include <malloc.h>
15 #include <unistd.h>
16 #include <fstream>
17 #include <sstream>
18 #include <string>
19 
20 #include "StMemStat.h"
21 #include "St_base/Stsstream.h"
22 #include "TList.h"
23 #include "TError.h"
24 #include <cassert>
25 #include "TSystem.h"
26 
27 Double_t StMemStat::fgUsed=0;
28 TList *StMemStat::fgList=0;
29 ClassImp(StMemStat)
30 
31 #define LOWEST_VAL 0.0000001
34 //______________________________________________________________________________
35 StMemStat::StMemStat(const char *name):TNamed(name,"")
36 {
37  int n = (char*)&fTally - (char*)&fLast + sizeof(fTally);
38  memset(&fLast,0,n);
39  fMin = 1.e+33;
40  fMax = -1.e+33;
41  if (!fgList) fgList=new TList;
42  fgList->Add(this);
43 }
44 //______________________________________________________________________________
45 StMemStat::~StMemStat()
46 {
47  fgList->Remove(this);
48  if (!fgList->First()) {delete fgList; fgList=0;}
49 }
50 
51 //______________________________________________________________________________
52 void StMemStat::Start()
53 {
54  fLast = Used();
55 }
56 
57 //______________________________________________________________________________
58 void StMemStat::Stop()
59 {
60  fTally++;
61  Double_t dif = Used() - fLast;
62 
63  //printf("DEBUG >> time distance between two stops Used=%f Last=%f\n",Used(),fLast);
64  if ( fabs(dif) < LOWEST_VAL ) dif = 0.0;
65  if ( dif < fMin ) fMin = dif;
66  if ( dif > fMax ) fMax = dif;
67 
68  fAver += dif;
69  fRms += (dif*dif);
70 
71 }
72 //______________________________________________________________________________
73 void StMemStat::Print(const char *) const
74 {
75  if (!fTally) return;
76  Double_t aver = fAver/fTally;
77  Double_t rms = ::sqrt(fabs(fRms/fTally - aver*aver));
78 
79  //printf("DEBUG :: %.10f %d %.10f %.10f\n",fAver,fTally,fRms,aver);
80  if ( fabs(aver) < LOWEST_VAL ) aver = 0.0;
81  if ( rms < LOWEST_VAL ) rms = 0.0;
82 
83  printf("%40.40s(%d)%12.6f%12.6f%12.6f%12.6f\n",
84  GetName(),fTally,fMin,aver,fMax,rms);
85 }
86 //______________________________________________________________________________
88 {
89 #define NUMTICKS (40+4*12+5)
90 
91  Double_t dmin=1.e+33, daver=0, dmax=-1.e+33, drms=0, dtally=0, dmp;
92  int i;
93 
94  if(!fgList) return;
95  fgList->Sort();
96  printf("%40.40s%12s%12s%12s%12s\n",
97  "StMemStat::Summary(calls)","Min ","Aver ","Max ","RMS ");
98 
99  for( i=0 ; i < NUMTICKS ; i++) printf("=");
100  printf("\n");
101 
102  TListIter next(fgList);
103  StMemStat *m;
104  while((m = (StMemStat*)next())){
105  if(!m->fTally) continue;
106  m->Print();
107  dtally++;
108  if (m->fMin < dmin) dmin=m->fMin;
109  if (m->fMax > dmax) dmax=m->fMax;
110  dmp = m->fAver/m->fTally;
111  daver += dmp;
112  drms += fabs(m->fRms/m->fTally-dmp*dmp);
113 
114  }
115  if(!dtally) return;
116 
117  for( i=0 ; i < NUMTICKS ; i++) printf("-");
118  printf("\n");
119 
120  //VP daver /= dtally;
121  drms = ::sqrt(fabs(drms));
122  printf("%40.40s(%d)%12.6f%12.6f%12.6f%12.6f\n",
123  "Total", (int)dtally, dmin, daver, dmax, drms);
124 
125  for( i=0 ; i < NUMTICKS ; i++) printf("=");
126  printf("\n");
127 
128 }
129 
130 
131 void StMemStat::doPs(std::string who, std::string where)
132 {
133  if (!gSystem->Getenv("StarEndMakerShell"))
134  return;
135 
136  PrintMem(FormString("QAInfo: doPs for %20s:%12s \t", who.c_str(), where.c_str()));
137  SaveProcStatus(where + ':' + who);
138 }
139 
140 
141 //______________________________________________________________________________
142 Double_t StMemStat::Used()
143 {
144  struct mallinfo info;
145  info = mallinfo();
146  return double(info.uordblks + info.usmblks)/1024/1024;
147 }
148 //______________________________________________________________________________
149 Double_t StMemStat::Free()
150 {
151  struct mallinfo info;
152  info = mallinfo();
153  return double(info.fordblks + info.fsmblks)/1024/1024;
154 }
155 
156 //______________________________________________________________________________
158 {
159  Double_t res=0;
160  int pid = ::getpid();
161  char line[100];
162  sprintf(line,"/proc/%d/status",pid);
163 
164 FILE *proc = fopen(line,"r");
165  if (proc) {//status file found
166  while (fgets(line,100,proc)) {
167  if (strncmp("VmSize:",line,7)==0) {
168  fclose(proc);
169  char *aft=0;
170  res = (strtod(line+7,&aft));
171  while ((++aft)[0]==' '){}
172  int b = 0;
173  if (strncmp("kB",aft,2)==0) b = 1024;
174  if (strncmp("mB",aft,2)==0) b = 1024*1024;
175  if (strncmp("gB",aft,2)==0) b = 1024*1024*1024;
176  res = (res*b)/(1024*1024);
177  return res;
178  }
179  }
180  fclose(proc);
181  }
182 // status file not found. Use ugly way via "ps"
183  static char *ps = 0;
184  if (!ps) {
185  ps = (char*)malloc(25);
186  sprintf(ps,"/bin/ps -l -p %d",pid);
187  }
188  FILE *pipe = ::popen(ps,"r");
189  if (!pipe) return 0.;
190 
191  char psBuf[130];
192  psBuf[0] = ' ';
193  while( !feof( pipe ) ) {
194  psBuf[1]=0;
195  if(!fgets( psBuf+1, 128, pipe)) continue;
196 // printf("%s\n",psBuf);
197  int ifild=0;char *c;
198 
199  for (c=psBuf; c[0]; c++) {
200  if (c[0]==' ' && c[1]!=' ') ifild++;
201  if (ifild == 10) break;
202  }
203  res = (Double_t) atoi(c+1);
204  if (res) break;
205  }
206  ::pclose(pipe);
207  res *=::getpagesize()/(1024.*1024.);
208 
209  return res;
210 }
211 //______________________________________________________________________________
212 void StMemStat::PrintMem(std::string prefix)
213 {
214  printf("%s\n", AsString(prefix).c_str());
215 }
216 
217 
218 std::string StMemStat::AsString(std::string prefix)
219 {
220  double alloc_used = Used();
221  double alloc_used_prev = fgUsed;
222  double alloc_free = Free();
223  double total = ProgSize();
224  fgUsed = alloc_used;
225 
226  return FormString("%s\t total =%10.6f heap =%10.6f and %10.6f(%+10.6f)",
227  prefix.c_str(), total, alloc_used, alloc_free, alloc_used - alloc_used_prev);
228 }
229 
230 //______________________________________________________________________________
232 {
233  Double_t used = Used();
234  printf("\nStMemStat: ");
235  printf("StMemStat::heap =%10.6f(%+10.6f)\n",used,used-fgUsed);
236  fgUsed = used;
237 }
238 //______________________________________________________________________________
239 void StMemStat::Streamer(TBuffer&)
240 {assert(0);}
241 //______________________________________________________________________________
242 // void StMemStat::ShowMembers(TMemberInspector& insp, char* parent){}
243 
244 
245 StMemStat::ProcStatusMap_t StMemStat::ReadProcStatus()
246 {
247  ProcStatusMap_t tokens{
248  {"VmPeak", 0},
249  {"VmSize", 0},
250  {"VmHWM", 0},
251  {"VmRSS", 0},
252  {"RssAnon", 0},
253  {"RssFile", 0},
254  {"RssShmem", 0}
255  };
256 
257  std::ifstream procfile("/proc/self/status");
258  std::string line;
259 
260  while (std::getline(procfile, line))
261  {
262  std::istringstream iss(line);
263  // First read the label
264  std::string label;
265  iss >> label;
266 
267  for (ProcStatus_t& token : tokens)
268  {
269  if (label.find(token.first) != std::string::npos) {
270  // Then read the value
271  iss >> token.second;
272  token.second /= 1024;
273  }
274  }
275  }
276 
277  return tokens;
278 }
279 
280 
281 void StMemStat::SaveProcStatus(std::string callerId)
282 {
283  static std::ofstream outfile("proc_status.csv");
284  static bool firstCall = true;
285 
286  const ProcStatusMap_t& tokens = ReadProcStatus();
287 
288  if (firstCall) {
289  outfile << "callerId";
290  for (const ProcStatus_t& token : tokens)
291  outfile << ", " << token.first;
292  outfile << '\n';
293  }
294 
295  outfile << callerId;
296  for (const ProcStatus_t& token : tokens)
297  outfile << ", " << token.second;
298  outfile << '\n';
299 
300  firstCall = false;
301 }
static void Summary()
Definition: StMemStat.cxx:87
static std::string AsString(std::string prefix="")
Returns a string with memory utilization estimates for the current process.
Definition: StMemStat.cxx:218
static Double_t Free()
Definition: StMemStat.cxx:149
static Double_t Used()
Definition: StMemStat.cxx:142
static void PrintMem(std::string prefix="")
Definition: StMemStat.cxx:212
static void PM()
Definition: StMemStat.cxx:231
std::string FormString(const std::string &format, Args...args)
Definition: Stsstream.h:40
static void SaveProcStatus(std::string callerId)
Definition: StMemStat.cxx:281
static Double_t ProgSize()
Definition: StMemStat.cxx:157