]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/STEERBase/AliSysInfo.cxx
Possibility to not write syswatch info to file (default)
[u/mrichter/AliRoot.git] / STEER / STEERBase / AliSysInfo.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
16
17 //
18 // Origin:  marian.ivanov@cern.ch
19 //
20 //  Make   a log file for the CPU and Memory usage
21 //
22 //  Principles:
23 //  Snapshots of the system information are writen to the text log files.
24 //  Text files were chosen in order to get the ouptu also in case code 
25 //  is crashing. 
26 //  Following information is stored in the log file:
27 //  TTimeStamp stamp;
28 //  CpuInfo_t  cpuInfo;
29 //  MemInfo_t  memInfo;
30 //  ProcInfo_t procInfo;
31 // 
32 //  Root TSystem is used to retrieve this information:
33 //  gSystem->GetCpuInfo(&cpuInfo, 10);
34 //  gSystem->GetMemInfo(&memInfo);
35 //  gSystem->GetProcInfo(&procInfo);
36 //  for details see:
37 //  http://root.cern.ch/root/html/TUnixSystem.html
38 //  http://root.cern.ch/root/html/ProcInfo_t.html
39 //  http://root.cern.ch/root/html/MemInfo_t.html
40 //  http://root.cern.ch/root/html/CpuInfo_t.html
41 //  -------------------------------------------------------------------
42 //  class CpuInfo_t
43 //   Float_t    fIdle   cpu idle percentage
44 //   Float_t    fLoad15m        cpu load average over 15 m
45 //   Float_t    fLoad1m cpu load average over 1 m
46 //   Float_t    fLoad5m cpu load average over 5 m
47 //   Float_t    fSys    cpu sys load in percentage
48 //   Float_t    fTotal  cpu user+sys load in percentage
49 //   Float_t    fUser   cpu user load in percentage
50
51 //  -------------------------------------------------------------------
52 //  class ProcInfo_t:
53 //  Float_t     fCpuSys system time used by this process in seconds
54 //  Float_t     fCpuUser        user time used by this process in seconds
55 //  Long_t      fMemResident    resident memory used by this process in KB
56 //  Long_t      fMemVirtual     virtual memory used by this process in KB
57 //  -------------------------------------------------------------------
58
59
60 //  The information from the AliSysInfo can be used as measurement
61 //  of the code quality. Be aware of the limitation induced by
62 //  using only system info described in the  AliSysInfo::Test() function
63 // 
64 //  The example usage of the AliSysInfo is shown in the
65 //  AliSysInfo::Test() example.
66 //  
67 //  
68 //
69 //  
70 //  The typical usage in the AliRoot code:
71 //  Make a set of stamps in the code in the place of interest
72 //  e.g. 
73 //
74 //  AliSysInfo::AddStamp("Start");
75 //
76 //  loader->UnloadRecPoints();
77 //    AliSysInfo::AddStamp(Form("LRec%s_%d",fgkDetectorName[iDet],eventNr), iDet,1,eventNr);
78 //
79
80 // The log file can be transformed to the tree - to make a visualization
81 // See $ALICE_ROOT/macros/PlotSysInfo.C as an example
82
83
84 #include <Riostream.h>
85 //#include "AliLog.h"
86 #include "TStopwatch.h"
87 #include "TSystem.h"
88 #include "TTree.h"
89 #include "TFile.h"
90
91 #include "TTimeStamp.h"
92 #include "AliSysInfo.h"
93 #include "TBufferFile.h"
94
95 //#include "TMemStatManager.h"  //USE IFDEF
96
97
98 using std::endl;
99 using std::cout;
100 using std::ios_base;
101 using std::setprecision;
102 ClassImp(AliSysInfo)
103
104 AliSysInfo* AliSysInfo::fInstance=0;
105 Bool_t AliSysInfo::fgVerbose = kFALSE;
106
107 AliSysInfo::AliSysInfo():
108     TObject(),
109     fSysWatch(0),
110     fTimer(0),
111     fMemStat(0),
112     fCallBackFunc(0),
113     fNCallBack(0)
114 {
115   fTimer = new TStopwatch;
116   fSysWatch  = new fstream("syswatch.log", ios_base::out|ios_base::trunc);
117
118   //hname/C:sname/C:sec/D:mI.fMemUsed/F:mI.fSwapUsed/F:pI.fMemResident/F:pI.fMemVirtual/F:cI.fUser/F:cI.fSys/F:cI.fCpuUser/F:pI.fCpuSys/F
119
120
121   (*fSysWatch) <<"hname"<<"/C:"               // hname - hostname  
122                <<"sname"<<"/C:"              // stamp name
123                <<"id0"<<"/I:"                // 0 id
124                <<"id1"<<"/I:"                // 1 id
125                <<"id2"<<"/I:"                // 1 id
126                <<"id3"<<"/I:"                // 1 id
127                <<"first"<<"/D:"              // first stamp
128     //
129                <<"stampSec"<<"/D:"         // time  - time stamp in seconds
130                <<"mi.fMemUsed"<<"/D:"       // system info 
131                <<"mi.fSwapUsed"<<"/D:"      //
132                <<"cI.fUser"<<"/D:"         //
133                <<"cI.fSys"<<"/D:"         //
134                <<"cI.fLoad1m"<<"/D:"         //
135                <<"cI.fLoad5m"<<"/D:"         //
136                <<"cI.fLoad15m"<<"/D:"         //
137     // 
138                <<"pI.fMemResident"<<"/D:"  // process info
139                <<"pI.fMemVirtual"<<"/D:"   //    
140                <<"pI.fCpuUser"<<"/D:"      //
141                <<"pI.fCpuSys"<<"/D:"       //
142     //
143                <<"stampOldSec"<<"/D:"         // time  - time stamp in seconds
144                <<"miOld.fMemUsed"<<"/D:"       // system info - previous
145                <<"miOld.fSwapUsed"<<"/D:"      //
146                <<"cIOld.fUser"<<"/D:"         //
147                <<"cIOld.fSys"<<"/D:"         //
148     // 
149                <<"pIOld.fMemResident"<<"/D:"  // process info -previous
150                <<"pIOld.fMemVirtual"<<"/D:"   //    
151                <<"pIOld.fCpuUser"<<"/D:"      //
152                <<"pIOld.fCpuSys"<<"/D:"       //
153     // 
154                <<"fileBytesRead"<<"/D:"       // file IO information
155                <<"fileBytesWritten"<<"/D:"    //    
156                <<"fileCounter"<<"/D:"         //
157                <<"fileReadCalls"<<"/D"        //
158                << endl;
159   
160 }
161
162
163
164
165 AliSysInfo * AliSysInfo::Instance(){
166   //
167   //
168   //
169   if (!fInstance){
170     fInstance = new AliSysInfo;
171   }
172   return fInstance;
173 }
174
175
176 void AliSysInfo::AddStamp(const char *sname, Int_t id0, Int_t id1, Int_t id2, Int_t id3){
177   //
178   // 
179   if (!fgVerbose) return;
180   //
181   //
182   TTimeStamp stamp;
183   CpuInfo_t  cpuInfo;
184   MemInfo_t  memInfo;
185   ProcInfo_t procInfo;  
186   gSystem->GetCpuInfo(&cpuInfo, 10);
187   gSystem->GetMemInfo(&memInfo);
188   gSystem->GetProcInfo(&procInfo);
189   //  procInfo.fMemVirtual/=1024;  //size in MBy
190   //procInfo.fMemResident/=1024;  //size in MBy
191
192   const char * hname = gSystem->HostName();
193
194   static Int_t entry=0;
195   static Double_t  first=stamp.GetSec()+stamp.GetNanoSec()/1000000000.;
196   //
197   static TTimeStamp stampOld;
198   static CpuInfo_t  cpuInfoOld;
199   static MemInfo_t  memInfoOld;
200   static ProcInfo_t procInfoOld;  
201   Double_t fileBytesRead    = TFile::GetFileBytesRead();
202   Double_t fileBytesWritten = TFile::GetFileBytesWritten();
203   Double_t fileCounter      = TFile::GetFileCounter();
204   Double_t fileReadCalls    = TFile::GetFileReadCalls();
205
206
207   (*(Instance()->fSysWatch)) 
208     << hname   <<"\t"               // hname - hostname  
209     << sname    <<"\t"              // stamp name
210     << id0      <<"\t"
211     << id1      <<"\t"
212     << id2      <<"\t"
213     << id3      <<"\t"
214     <<setprecision(15)<< first    <<"\t"              // first stamp               
215     //
216     <<setprecision(15)<< stamp.GetSec()+stamp.GetNanoSec()/1000000000.<<"\t"         // time  - time stamp in seconds
217     << memInfo.fMemUsed<<"\t"       // system info 
218     << memInfo.fSwapUsed<<"\t"      //
219     << cpuInfo.fUser <<"\t"         //
220     << cpuInfo.fSys  <<"\t"         //
221     << cpuInfo.fLoad1m  <<"\t"         //
222     << cpuInfo.fLoad5m  <<"\t"         //
223     << cpuInfo.fLoad15m  <<"\t"         //
224     // 
225     <<setprecision(15)<< procInfo.fMemResident/1024.<<"\t"  // process info
226     <<setprecision(15)<< procInfo.fMemVirtual/1024.<<"\t"   //    
227     << procInfo.fCpuUser<<"\t"      //
228     << procInfo.fCpuSys<<"\t"       //
229     //
230     <<setprecision(15)<< stampOld.GetSec()+stampOld.GetNanoSec()/1000000000.<<"\t"         // time  - time stamp in seconds
231     << memInfoOld.fMemUsed<<"\t"       // system info - previous
232     << memInfoOld.fSwapUsed<<"\t"      //
233     << cpuInfoOld.fUser <<"\t"         //
234     << cpuInfoOld.fSys  <<"\t"         //
235     // 
236     <<setprecision(15)<< procInfoOld.fMemResident/1024.<<"\t"  // process info -previous
237     <<setprecision(15)<< procInfoOld.fMemVirtual/1024.<<"\t"   //    
238     << procInfoOld.fCpuUser<<"\t"      //
239     << procInfoOld.fCpuSys<<"\t"       //
240     //
241     <<fileBytesRead<<"\t"           // file IO information
242     <<fileBytesWritten<<"\t"        //    
243     <<fileCounter<<"\t"             //
244     <<fileReadCalls<<"\t"            //
245     << endl;
246
247   stampOld   = stamp;
248   cpuInfoOld = cpuInfo;
249   memInfoOld = memInfo;
250   procInfoOld= procInfo;
251
252   //  if (fInstance->fMemStat) fInstance->fMemStat->AddStamps(sname);
253   for (Int_t icallback=0; icallback<Instance()->fNCallBack; icallback++){
254     Instance()->fCallBackFunc[icallback](sname);
255   }
256   entry++;
257 }
258
259
260 TTree * AliSysInfo::MakeTree(const char *lname){
261   // char * lname = "syswatch.log"
262   TTree * tree = new TTree;
263   tree->ReadFile(lname);
264   tree->SetAlias("deltaT","stampSec-stampOldSec");
265   tree->SetAlias("T","stampSec-first");
266   tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
267   tree->SetAlias("VM","pI.fMemVirtual");
268   return tree;
269 }
270
271
272 Bool_t AliSysInfo::Contain(const char * str1, const char * str2){
273   //
274   //
275   //
276   TString str(str1);
277   return str.Contains(str2);
278 }
279
280
281
282 void AliSysInfo::OpenMemStat(){
283   //
284   //
285   //
286   //USE IFDEF if MEMSTAT ENABLED  
287   //  Instance()->fMemStat = TMemStatManager::GetInstance();
288   //   Instance()->fMemStat->SetAutoStamp(10000000, 10000000,1000000);
289   //   Instance()->fMemStat->Enable();  
290 }
291
292 void AliSysInfo::CloseMemStat(){
293   //
294   //
295   //
296   //USE IFDEF if MEMSTAT ENABLED
297   //if (Instance()->fMemStat  == TMemStatManager::GetInstance()) Instance()->fMemStat->Close();
298   //Instance()->fMemStat=0;
299 }
300
301
302
303 void AliSysInfo::AddCallBack(StampCallback_t callback){
304   //
305   // add cal back function
306   //
307   AliSysInfo *info =  Instance();
308   if (!info->fCallBackFunc)
309     info->fCallBackFunc = new StampCallback_t[100];
310   info->fCallBackFunc[info->fNCallBack]=callback;
311   info->fNCallBack++;
312 }
313
314
315
316 TTree*  AliSysInfo::Test(){
317   //
318   // Test example for AliSysInfo:
319   // 1. Make huge memory leak
320   // 2. Slow down execution
321   /*
322     To use the test:
323     TTree * tree = AliSysInfo::Test();
324     // Make alias what we set as input
325     tree->SetAlias("deltaVMIn","(id0*100000+id1*10000+id2*1000)/1000000.")
326     tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
327     tree->SetAlias("deltaTIn","(id1+id0*10)");
328     tree->SetAlias("deltaT","stampSec-stampOldSec");
329     //
330     tree->SetMarkerStyle(23); tree->SetMarkerSize(0.5);
331     // Memory usage
332     tree->Draw("deltaVM:deltaVMIn","Entry$>0");
333     // or alternative
334     tree->Draw("deltaVM:deltaVMIn","Entry$>0","prof");
335     //
336     // draw time usage
337     tree->Draw("deltaT:deltaTIn","Entry$>0"); 
338   */
339   //
340   // The delta of VM as obtained from the AliSysInfo starts to be proportional
341   // to  the input allocation after 0.12 MBy (and it is system dependent) 
342   // Bellow these limit the deltaVM can be used only in mean.
343   // (compare first and  profile histogram)
344   for (Int_t id0=0; id0<5; id0++)
345     for (Int_t id1=1; id1<10; id1++)
346       for (Int_t id2=0; id2<20; id2++){
347         new Char_t[id2*1000+id1*10000+id0*100000];  // emulate memory leak
348         gSystem->Sleep(id1+id0*10);         // emulate CPU usage 
349         AliSysInfo::AddStamp("Leak",id0,id1,id2);
350       }
351   TTree * tree = AliSysInfo::MakeTree("syswatch.log");
352   return tree;  
353 }
354
355 Double_t AliSysInfo::EstimateObjectSize(TObject* object){
356   //
357   // Estimate size of object as represented in the memory size in bytes
358   // Warnings:
359   //  1. Only data memebrs which are persistent are counted
360   //  2. Local copy of the object is temporary created in memory
361   //  3. Do not use it in standard programs, time and memory consument procedure
362   //
363   if (!object) return 0;
364   TBufferFile * file = new TBufferFile(TBuffer::kWrite);
365   file->WriteObject(object);
366   Double_t size=file->Length();
367   delete file;
368   return size;
369 }