]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliMemoryWatcher.cxx
Restored functionality
[u/mrichter/AliRoot.git] / STEER / AliMemoryWatcher.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 //_________________________________________________________________________
18 //Basic Memory Leak utility.    
19 //     You can use this tiny class to *see* if your program is leaking.
20 //     Usage:
21 //     AliMemoryWatcher memwatcher;
22 //     some program loop on events here {
23 //       if ( nevents % x == 0 ) 
24 //       {
25 //       // take a sample every x events
26 //         memwatcher.Watch(nevents);
27 //       }
28 //     }
29 //     TFile f("out.root","RECREATE");
30 //     memwatcher.Write();
31 //     f.Close();
32 //     In the output root file you'll get 3 graphs representing
33 //     the evolAliPHOSon, as a function of the number of events, of :
34 //     - VSIZE is the virtual size (in KBytes) of your program, that is sort of
35 //     the total memory used
36 //     - RSSIZE is the resident size (in KBytes), that is, the part of your 
37 //     program which is really in physical memory.
38 //     - TIME is an estimate of time per event (really it's the time elasped
39 //     between two calls to watch method)
40 //     WARNING: this is far from a bulletproof memory report (it's basically 
41 //     using UNIX command ps -h -p [PID] -o vsize,rssize to do its job).
42 //     It has only been tested on Linux so far.    
43 //     But by fitting the VSIZE by a pol1 under ROOT, you'll see right away
44 //     by how much your program is leaking.          
45 //*-- Author: Laurent Aphecetche(SUBATECH)
46
47 // --- std system ---
48 #include <cassert> 
49 #ifdef __APPLE__
50 #include <stdlib.h>
51 #else
52 #include <malloc.h>
53 #endif
54 // --- AliRoot header files ---
55 #include "AliLog.h"
56 #include "AliMemoryWatcher.h"
57 // --- ROOT system ---
58 #include "TSystem.h"
59 #include "TGraph.h"
60 #include "TH2.h"
61 #include "TStopwatch.h"
62 #include "TError.h"
63
64 ClassImp(AliMemoryWatcher)
65
66 //_____________________________________________________________________________
67 AliMemoryWatcher::AliMemoryWatcher(UInt_t maxsize) :
68   TObject(),
69   fUseMallinfo(kTRUE),
70   fPID(gSystem->GetPid()),
71   fMAXSIZE(maxsize),
72   fSize(0),
73   fX(new Int_t[fMAXSIZE]),
74   fVSIZE(new Int_t[fMAXSIZE]),
75   fRSSIZE(new Int_t[fMAXSIZE]),
76   fTIME(new Double_t[fMAXSIZE]),
77   fTimer(0),
78   fDisabled(kFALSE)
79 {
80   //
81   //ctor
82   //
83   sprintf(fCmd,"ps -h -p %d -o vsz,rss | grep -v VSZ",fPID);
84 }
85
86 //_____________________________________________________________________________
87 AliMemoryWatcher::AliMemoryWatcher(const AliMemoryWatcher& mw):
88   TObject(mw),
89   fUseMallinfo(mw.fUseMallinfo),
90   fPID(mw.fPID),
91   fMAXSIZE(mw.fMAXSIZE),
92   fSize(0),
93   fX(new Int_t[fMAXSIZE]),
94   fVSIZE(new Int_t[fMAXSIZE]),
95   fRSSIZE(new Int_t[fMAXSIZE]),
96   fTIME(new Double_t[fMAXSIZE]),
97   fTimer(0),
98   fDisabled(kFALSE)
99 {
100   //copy ctor
101   strcpy(fCmd, mw.fCmd) ; 
102 }
103
104 //_____________________________________________________________________________
105 AliMemoryWatcher::~AliMemoryWatcher()
106 {
107   // dtor
108   delete[] fVSIZE;
109   delete[] fRSSIZE;
110   delete[] fX;
111   delete[] fTIME;
112   delete fTimer;
113 }
114 //_____________________________________________________________________________
115 void AliMemoryWatcher::Watch(Int_t x)
116 {
117   // Sets the point where CPU parameters have to be monitored
118   if ( !fDisabled && fSize < fMAXSIZE ) {
119     if ( fSize==0 ) {
120       assert(fTimer==0);
121       fTimer = new TStopwatch;
122       fTimer->Start(true);
123       fTimer->Stop();
124     }
125     if ( fUseMallinfo ) {
126 #ifdef __linux
127       static struct mallinfo meminfo;
128       meminfo = mallinfo();
129       fX[fSize] = x ;
130       fVSIZE[fSize] = (meminfo.hblkhd + meminfo.uordblks) / 1024;
131       fRSSIZE[fSize] =  meminfo.uordblks / 1024;
132       fTIME[fSize] = fTimer->CpuTime();
133       fSize++;
134 #else
135       AliFatal("Please SetUseMallinfo to kFALSE on this system");
136 #endif
137     } else {
138       static Int_t vsize, rssize;
139       static FILE* pipe = 0;
140       pipe = popen(fCmd,"r");
141       if ( pipe ) {
142     
143         fscanf(pipe,"%d %d",&vsize,&rssize);
144       
145         fX[fSize] = x ;
146         fVSIZE[fSize] = vsize ;
147         fRSSIZE[fSize] = rssize ;
148         fTIME[fSize] = fTimer->CpuTime();
149         fSize++;
150       }
151       assert(pclose(pipe)!=-1);
152     }
153     fTimer->Start(true);
154   }
155   else {
156     fDisabled=true;
157     AliError("I'm full !" ) ;
158   }
159 }
160 //_____________________________________________________________________________
161 TGraph*
162 AliMemoryWatcher::GraphVSIZE(void)
163 {
164   // Fills the graph with the virtual memory sized used
165   TGraph* g = 0;
166   if ( Size() )
167     {
168       g = new TGraph(Size());
169       Int_t i ; 
170       for (i=0; i < g->GetN(); i++ ) {
171         g->SetPoint(i,X(i),VSIZE(i));
172       }
173     }
174   return g;
175 }
176 //_____________________________________________________________________________
177 TGraph*
178 AliMemoryWatcher::GraphRSSIZE(void)
179 {
180   // Fills the graph with the real memory sized used
181   TGraph* g = 0;
182   if ( Size() ) 
183     {
184       g = new TGraph(Size());
185       Int_t i ; 
186       for (i=0; i < g->GetN(); i++ ) {
187         g->SetPoint(i,X(i),RSSIZE(i));
188       }
189     }
190   return g;
191 }
192 //_____________________________________________________________________________
193 TGraph*
194 AliMemoryWatcher::GraphTIME(void)
195 {
196   // Fills the raph with the used CPU time
197   TGraph* g = 0;
198   if ( Size() ) 
199     {
200       g = new TGraph(Size());
201       Int_t i ; 
202       for (i=0; i < g->GetN(); i++ ) {
203         g->SetPoint(i,X(i),TIME(i));
204       }
205     }
206   return g;
207 }
208 //_____________________________________________________________________________
209 TH2*
210 AliMemoryWatcher::Frame(void) const
211 {
212   //creates the frame histo in which the graphs will be plotted 
213   Double_t xmin=1E30;
214   Double_t xmax=0;
215   Double_t ymin=1;
216   Double_t ymax=0;
217   UInt_t i ; 
218   for (i=0; i < Size() ; i++ ) {
219     if ( X(i) < xmin ) xmin = X(i);
220     if ( X(i) > xmax ) xmax = X(i);
221     Double_t y = VSIZE(i)+RSSIZE(i);
222     if ( y > ymax ) ymax = y;
223     if ( VSIZE(i) < ymin ) ymin = VSIZE(i);
224     if ( RSSIZE(i) < ymin ) ymin = RSSIZE(i);
225   }
226   TH2F* h = new TH2F("frame","",10,xmin,xmax,10,ymin*0.8,ymax*1.2);
227   return h;
228 }
229 //_____________________________________________________________________________
230 Int_t
231 AliMemoryWatcher::WriteToFile()
232 {
233   // Stores the graphs in a file 
234   if ( GraphVSIZE() ) GraphVSIZE()->Write("VSIZE",TObject::kOverwrite);
235   if ( GraphRSSIZE() ) GraphRSSIZE() ->Write("RSSIZE",TObject::kOverwrite);
236   if ( GraphTIME() ) GraphTIME()->Write("TIME",TObject::kOverwrite);
237   return 0;
238 }