1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 // Origin: marian.ivanov@cern.ch
20 // Make a log file for the CPU and Memory usage
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
26 // Following information is stored in the log file:
30 // ProcInfo_t procInfo;
32 // Root TSystem is used to retrieve this information:
33 // gSystem->GetCpuInfo(&cpuInfo, 10);
34 // gSystem->GetMemInfo(&memInfo);
35 // gSystem->GetProcInfo(&procInfo);
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 // -------------------------------------------------------------------
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
51 // -------------------------------------------------------------------
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 // -------------------------------------------------------------------
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
64 // The example usage of the AliSysInfo is shown in the
65 // AliSysInfo::Test() example.
70 // The typical usage in the AliRoot code:
71 // Make a set of stamps in the code in the place of interest
74 // AliSysInfo::AddStamp("Start");
76 // loader->UnloadRecPoints();
77 // AliSysInfo::AddStamp(Form("LRec%s_%d",fgkDetectorName[iDet],eventNr), iDet,1,eventNr);
80 // The log file can be transformed to the tree - to make a visualization
81 // See $ALICE_ROOT/macros/PlotSysInfo.C as an example
84 #include <Riostream.h>
86 #include "TStopwatch.h"
91 #include "TTimeStamp.h"
92 #include "AliSysInfo.h"
93 #include "TBufferFile.h"
95 //#include "TMemStatManager.h" //USE IFDEF
101 using std::setprecision;
104 AliSysInfo* AliSysInfo::fInstance=0;
105 Bool_t AliSysInfo::fgVerbose = kFALSE;
107 AliSysInfo::AliSysInfo():
115 fTimer = new TStopwatch;
116 fSysWatch = new fstream("syswatch.log", ios_base::out|ios_base::trunc);
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
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
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:" //
138 <<"pI.fMemResident"<<"/D:" // process info
139 <<"pI.fMemVirtual"<<"/D:" //
140 <<"pI.fCpuUser"<<"/D:" //
141 <<"pI.fCpuSys"<<"/D:" //
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:" //
149 <<"pIOld.fMemResident"<<"/D:" // process info -previous
150 <<"pIOld.fMemVirtual"<<"/D:" //
151 <<"pIOld.fCpuUser"<<"/D:" //
152 <<"pIOld.fCpuSys"<<"/D:" //
154 <<"fileBytesRead"<<"/D:" // file IO information
155 <<"fileBytesWritten"<<"/D:" //
156 <<"fileCounter"<<"/D:" //
157 <<"fileReadCalls"<<"/D" //
165 AliSysInfo * AliSysInfo::Instance(){
170 fInstance = new AliSysInfo;
176 void AliSysInfo::AddStamp(const char *sname, Int_t id0, Int_t id1, Int_t id2, Int_t id3){
179 if (!fgVerbose) return;
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
192 const char * hname = gSystem->HostName();
194 static Int_t entry=0;
195 static Double_t first=stamp.GetSec()+stamp.GetNanoSec()/1000000000.;
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();
207 (*(Instance()->fSysWatch))
208 << hname <<"\t" // hname - hostname
209 << sname <<"\t" // stamp name
214 <<setprecision(15)<< first <<"\t" // first stamp
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" //
225 <<setprecision(15)<< procInfo.fMemResident/1024.<<"\t" // process info
226 <<setprecision(15)<< procInfo.fMemVirtual/1024.<<"\t" //
227 << procInfo.fCpuUser<<"\t" //
228 << procInfo.fCpuSys<<"\t" //
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" //
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" //
241 <<fileBytesRead<<"\t" // file IO information
242 <<fileBytesWritten<<"\t" //
243 <<fileCounter<<"\t" //
244 <<fileReadCalls<<"\t" //
248 cpuInfoOld = cpuInfo;
249 memInfoOld = memInfo;
250 procInfoOld= procInfo;
252 // if (fInstance->fMemStat) fInstance->fMemStat->AddStamps(sname);
253 for (Int_t icallback=0; icallback<Instance()->fNCallBack; icallback++){
254 Instance()->fCallBackFunc[icallback](sname);
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");
272 Bool_t AliSysInfo::Contain(const char * str1, const char * str2){
277 return str.Contains(str2);
282 void AliSysInfo::OpenMemStat(){
286 //USE IFDEF if MEMSTAT ENABLED
287 // Instance()->fMemStat = TMemStatManager::GetInstance();
288 // Instance()->fMemStat->SetAutoStamp(10000000, 10000000,1000000);
289 // Instance()->fMemStat->Enable();
292 void AliSysInfo::CloseMemStat(){
296 //USE IFDEF if MEMSTAT ENABLED
297 //if (Instance()->fMemStat == TMemStatManager::GetInstance()) Instance()->fMemStat->Close();
298 //Instance()->fMemStat=0;
303 void AliSysInfo::AddCallBack(StampCallback_t callback){
305 // add cal back function
307 AliSysInfo *info = Instance();
308 if (!info->fCallBackFunc)
309 info->fCallBackFunc = new StampCallback_t[100];
310 info->fCallBackFunc[info->fNCallBack]=callback;
316 TTree* AliSysInfo::Test(){
318 // Test example for AliSysInfo:
319 // 1. Make huge memory leak
320 // 2. Slow down execution
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");
330 tree->SetMarkerStyle(23); tree->SetMarkerSize(0.5);
332 tree->Draw("deltaVM:deltaVMIn","Entry$>0");
334 tree->Draw("deltaVM:deltaVMIn","Entry$>0","prof");
337 tree->Draw("deltaT:deltaTIn","Entry$>0");
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);
351 TTree * tree = AliSysInfo::MakeTree("syswatch.log");
355 Double_t AliSysInfo::EstimateObjectSize(TObject* object){
357 // Estimate size of object as represented in the memory size in bytes
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
363 if (!object) return 0;
364 TBufferFile * file = new TBufferFile(TBuffer::kWrite);
365 file->WriteObject(object);
366 Double_t size=file->Length();