New utility class that watches the memory usage .... from Laurent Aphecetche for...
[u/mrichter/AliRoot.git] / PHOS / AliPHOSMemoryWatcher.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15 /* $Id$ */
16 //_________________________________________________________________________
17 /*Basic Memory Leak utility.
18     
19     You can use this tiny class to *see* if your program is leaking.
20
21     Usage:
22
23     AliPHOSMemoryWatcher memwatcher;
24
25     some program loop on events here {
26       if ( nevents % x == 0 ) 
27       {
28       // take a sample every x events
29         memwatcher.watch(nevents);
30       }
31     }
32
33     TFile f("out.root","RECREATE");
34     memwatcher.write();
35     f.Close();
36
37     In the output root file you'll get 3 graphs representing
38     the evolAliPHOSon, as a function of the number of events, of :
39     - VSIZE is the virtual size (in KBytes) of your program, that is sort of
40     the total memory used
41     - RSSIZE is the resident size (in KBytes), that is, the part of your 
42     program which is really in physical memory.
43     - TIME is an estimate of time per event (really it's the time elasped
44     between two calls to watch method)
45
46     WARNING: this is far from a bulletproof memory report (it's basically 
47     using UNIX command ps -h -p [PID] -o vsize,rssize to do its job).
48     It has only been tested on Linux so far.
49     
50     But by fitting the VSIZE by a pol1 under ROOT, you'll see right away
51     by how much your program is leaking.
52 */             
53 //*-- Author: Laurent Aphecetche(SUBATECH)
54
55
56 // --- std system ---
57 #include <iostream>
58 #include <cstdio>
59 #include <cstdlib>
60 #include <cassert>
61
62 // --- AliRoot header files ---
63 #include "AliPHOSMemoryWatcher.h"
64
65 // --- ROOT system ---
66 #include "TSystem.h"
67 #include "TGraph.h"
68 #include "TH2.h"
69 #include "TStopwatch.h"
70
71 //_____________________________________________________________________________
72 AliPHOSMemoryWatcher::AliPHOSMemoryWatcher(unsigned int maxsize)
73 {
74   fMAXSIZE=maxsize;
75   fPID = gSystem->GetPid();
76   sprintf(fCmd,"ps -h -p %d -o vsize,rssize",fPID);
77
78   fX = new int[fMAXSIZE];
79   fVSIZE = new int[fMAXSIZE];
80   fRSSIZE = new int[fMAXSIZE];
81   fTIME = new double[fMAXSIZE];
82   fSize=0;
83   fDisabled=false;
84   fTimer=0;
85 }
86
87 //_____________________________________________________________________________
88 AliPHOSMemoryWatcher::~AliPHOSMemoryWatcher()
89 {
90   delete[] fVSIZE;
91   delete[] fRSSIZE;
92   delete[] fX;
93   delete[] fTIME;
94   delete fTimer;
95 }
96
97 //_____________________________________________________________________________
98 void AliPHOSMemoryWatcher::watch(int x)
99 {
100   if ( !fDisabled && fSize < fMAXSIZE ) {
101
102     if ( fSize==0 ) {
103       assert(fTimer==0);
104       fTimer = new TStopwatch;
105       fTimer->Start(true);
106       fTimer->Stop();
107     }
108
109     static int vsize, rssize;
110
111     static FILE* pipe = 0;
112
113     pipe = popen(fCmd,"r");
114
115     if ( pipe ) {
116     
117       fscanf(pipe,"%d %d",&vsize,&rssize);
118       
119       fX[fSize] = x ;
120       fVSIZE[fSize] = vsize ;
121       fRSSIZE[fSize] = rssize ;
122       fTIME[fSize] = fTimer->CpuTime();
123       fSize++;
124     }
125
126     assert(pclose(pipe)!=-1);
127
128     fTimer->Start(true);
129
130   }
131   else {
132     fDisabled=true;
133     cerr << "AliPHOSMemoryWatcher::watch : I'm full !" << endl;
134   }
135 }
136
137 //_____________________________________________________________________________
138 TGraph*
139 AliPHOSMemoryWatcher::graphVSIZE(void)
140 {
141   TGraph* g = 0;
142
143   if ( size() )
144     {
145       g = new TGraph(size());
146       for (int i=0; i < g->GetN(); i++ ) {
147         g->SetPoint(i,X(i),VSIZE(i));
148       }
149     }
150   return g;
151 }
152
153 //_____________________________________________________________________________
154 TGraph*
155 AliPHOSMemoryWatcher::graphRSSIZE(void)
156 {
157   TGraph* g = 0;
158   if ( size() ) 
159     {
160       g = new TGraph(size());
161       for (int i=0; i < g->GetN(); i++ ) {
162         g->SetPoint(i,X(i),RSSIZE(i));
163       }
164     }
165   return g;
166 }
167
168 //_____________________________________________________________________________
169 TGraph*
170 AliPHOSMemoryWatcher::graphTIME(void)
171 {
172   TGraph* g = 0;
173   if ( size() ) 
174     {
175       g = new TGraph(size());
176       for (int i=0; i < g->GetN(); i++ ) {
177         g->SetPoint(i,X(i),TIME(i));
178       }
179     }
180   return g;
181 }
182
183 //_____________________________________________________________________________
184 TH2*
185 AliPHOSMemoryWatcher::frame(void)
186 {
187   double xmin=1E30;
188   double xmax=0;
189   double ymin=1;
190   double ymax=0;
191
192   for (unsigned int i=0; i < size() ; i++ ) {
193     if ( X(i) < xmin ) xmin = X(i);
194     if ( X(i) > xmax ) xmax = X(i);
195
196     double y = VSIZE(i)+RSSIZE(i);
197
198     if ( y > ymax ) ymax = y;
199
200     if ( VSIZE(i) < ymin ) ymin = VSIZE(i);
201     if ( RSSIZE(i) < ymin ) ymin = RSSIZE(i);
202   }
203
204   TH2F* h = new TH2F("frame","",10,xmin,xmax,10,ymin*0.8,ymax*1.2);
205
206   return h;
207 }
208
209 //_____________________________________________________________________________
210 void 
211 AliPHOSMemoryWatcher::write(void)
212 {
213   if ( graphVSIZE() ) graphVSIZE()->Write("VSIZE",TObject::kOverwrite);
214   if ( graphRSSIZE() ) graphRSSIZE()->Write("RSSIZE",TObject::kOverwrite);
215   if ( graphTIME() ) graphTIME()->Write("TIME",TObject::kOverwrite);
216 }
217