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