Line data Source code
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 : #include "TTreePlayer.h"
95 :
96 : //#include "TMemStatManager.h" //USE IFDEF
97 :
98 :
99 : using std::endl;
100 : using std::cout;
101 : using std::ios_base;
102 : using std::setprecision;
103 176 : ClassImp(AliSysInfo)
104 :
105 : AliSysInfo* AliSysInfo::fInstance=0;
106 : Bool_t AliSysInfo::fgVerbose = kTRUE;
107 : Bool_t AliSysInfo::fgDisabled = kFALSE;
108 :
109 : AliSysInfo::AliSysInfo():
110 3 : TObject(),
111 3 : fSysWatch(0),
112 3 : fTimer(0),
113 3 : fMemStat(0),
114 3 : fCallBackFunc(0),
115 3 : fNCallBack(0)
116 15 : {
117 3 : if (fgDisabled) return;
118 9 : fTimer = new TStopwatch;
119 9 : fSysWatch = new fstream("syswatch.log", ios_base::out|ios_base::trunc);
120 :
121 : //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
122 :
123 :
124 6 : (*fSysWatch) <<"hname"<<"/C:" // hname - hostname
125 6 : <<"sname"<<"/C:" // stamp name
126 6 : <<"id0"<<"/I:" // 0 id
127 6 : <<"id1"<<"/I:" // 1 id
128 6 : <<"id2"<<"/I:" // 1 id
129 6 : <<"id3"<<"/I:" // 1 id
130 6 : <<"first"<<"/D:" // first stamp
131 : //
132 6 : <<"stampSec"<<"/D:" // time - time stamp in seconds
133 6 : <<"mi.fMemUsed"<<"/D:" // system info
134 6 : <<"mi.fSwapUsed"<<"/D:" //
135 6 : <<"cI.fUser"<<"/D:" //
136 6 : <<"cI.fSys"<<"/D:" //
137 6 : <<"cI.fLoad1m"<<"/D:" //
138 6 : <<"cI.fLoad5m"<<"/D:" //
139 6 : <<"cI.fLoad15m"<<"/D:" //
140 : //
141 6 : <<"pI.fMemResident"<<"/D:" // process info
142 6 : <<"pI.fMemVirtual"<<"/D:" //
143 6 : <<"pI.fCpuUser"<<"/D:" //
144 6 : <<"pI.fCpuSys"<<"/D:" //
145 : //
146 6 : <<"stampOldSec"<<"/D:" // time - time stamp in seconds
147 6 : <<"miOld.fMemUsed"<<"/D:" // system info - previous
148 6 : <<"miOld.fSwapUsed"<<"/D:" //
149 6 : <<"cIOld.fUser"<<"/D:" //
150 6 : <<"cIOld.fSys"<<"/D:" //
151 : //
152 6 : <<"pIOld.fMemResident"<<"/D:" // process info -previous
153 6 : <<"pIOld.fMemVirtual"<<"/D:" //
154 6 : <<"pIOld.fCpuUser"<<"/D:" //
155 6 : <<"pIOld.fCpuSys"<<"/D:" //
156 : //
157 6 : <<"fileBytesRead"<<"/D:" // file IO information
158 6 : <<"fileBytesWritten"<<"/D:" //
159 6 : <<"fileCounter"<<"/D:" //
160 6 : <<"fileReadCalls"<<"/D" //
161 3 : << endl;
162 :
163 6 : }
164 :
165 :
166 :
167 :
168 : AliSysInfo * AliSysInfo::Instance(){
169 : //
170 : //
171 : //
172 2952 : if (!fInstance){
173 6 : fInstance = new AliSysInfo;
174 3 : }
175 1476 : return fInstance;
176 0 : }
177 :
178 :
179 : void AliSysInfo::AddStamp(const char *sname, Int_t id0, Int_t id1, Int_t id2, Int_t id3){
180 : //
181 : //
182 1476 : if (!fgVerbose) return;
183 : //
184 : //
185 738 : TTimeStamp stamp;
186 738 : CpuInfo_t cpuInfo;
187 738 : MemInfo_t memInfo;
188 738 : ProcInfo_t procInfo;
189 738 : gSystem->GetCpuInfo(&cpuInfo, 10);
190 738 : gSystem->GetMemInfo(&memInfo);
191 738 : gSystem->GetProcInfo(&procInfo);
192 : // procInfo.fMemVirtual/=1024; //size in MBy
193 : //procInfo.fMemResident/=1024; //size in MBy
194 :
195 738 : const char * hname = gSystem->HostName();
196 :
197 : static Int_t entry=0;
198 744 : static Double_t first=stamp.GetSec()+stamp.GetNanoSec()/1000000000.;
199 : //
200 747 : static TTimeStamp stampOld;
201 747 : static CpuInfo_t cpuInfoOld;
202 747 : static MemInfo_t memInfoOld;
203 747 : static ProcInfo_t procInfoOld;
204 1476 : Double_t fileBytesRead = TFile::GetFileBytesRead();
205 1476 : Double_t fileBytesWritten = TFile::GetFileBytesWritten();
206 1476 : Double_t fileCounter = TFile::GetFileCounter();
207 1476 : Double_t fileReadCalls = TFile::GetFileReadCalls();
208 :
209 :
210 1476 : (*(Instance()->fSysWatch))
211 1476 : << hname <<"\t" // hname - hostname
212 1476 : << sname <<"\t" // stamp name
213 1476 : << id0 <<"\t"
214 1476 : << id1 <<"\t"
215 1476 : << id2 <<"\t"
216 1476 : << id3 <<"\t"
217 2952 : <<setprecision(15)<< first <<"\t" // first stamp
218 : //
219 2952 : <<setprecision(15)<< stamp.GetSec()+stamp.GetNanoSec()/1000000000.<<"\t" // time - time stamp in seconds
220 1476 : << memInfo.fMemUsed<<"\t" // system info
221 1476 : << memInfo.fSwapUsed<<"\t" //
222 1476 : << cpuInfo.fUser <<"\t" //
223 1476 : << cpuInfo.fSys <<"\t" //
224 1476 : << cpuInfo.fLoad1m <<"\t" //
225 1476 : << cpuInfo.fLoad5m <<"\t" //
226 1476 : << cpuInfo.fLoad15m <<"\t" //
227 : //
228 2952 : <<setprecision(15)<< procInfo.fMemResident/1024.<<"\t" // process info
229 2952 : <<setprecision(15)<< procInfo.fMemVirtual/1024.<<"\t" //
230 1476 : << procInfo.fCpuUser<<"\t" //
231 1476 : << procInfo.fCpuSys<<"\t" //
232 : //
233 2952 : <<setprecision(15)<< stampOld.GetSec()+stampOld.GetNanoSec()/1000000000.<<"\t" // time - time stamp in seconds
234 1476 : << memInfoOld.fMemUsed<<"\t" // system info - previous
235 1476 : << memInfoOld.fSwapUsed<<"\t" //
236 1476 : << cpuInfoOld.fUser <<"\t" //
237 1476 : << cpuInfoOld.fSys <<"\t" //
238 : //
239 2952 : <<setprecision(15)<< procInfoOld.fMemResident/1024.<<"\t" // process info -previous
240 2952 : <<setprecision(15)<< procInfoOld.fMemVirtual/1024.<<"\t" //
241 1476 : << procInfoOld.fCpuUser<<"\t" //
242 1476 : << procInfoOld.fCpuSys<<"\t" //
243 : //
244 1476 : <<fileBytesRead<<"\t" // file IO information
245 1476 : <<fileBytesWritten<<"\t" //
246 1476 : <<fileCounter<<"\t" //
247 1476 : <<fileReadCalls<<"\t" //
248 738 : << endl;
249 :
250 738 : stampOld = stamp;
251 738 : cpuInfoOld = cpuInfo;
252 738 : memInfoOld = memInfo;
253 738 : procInfoOld= procInfo;
254 :
255 : // if (fInstance->fMemStat) fInstance->fMemStat->AddStamps(sname);
256 2214 : for (Int_t icallback=0; icallback<Instance()->fNCallBack; icallback++){
257 0 : Instance()->fCallBackFunc[icallback](sname);
258 : }
259 738 : entry++;
260 1476 : }
261 :
262 :
263 : TTree * AliSysInfo::MakeTree(const char *lname, const char * fout){
264 : // char * lname = "syswatch.log"
265 0 : TTree * tree = new TTree;
266 0 : tree->ReadFile(lname);
267 0 : tree->SetAlias("deltaT","stampSec-stampOldSec");
268 0 : tree->SetAlias("T","stampSec-first");
269 0 : tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
270 0 : tree->SetAlias("VM","pI.fMemVirtual");
271 0 : tree->SetAlias("deltaRM","(pI.fMemResident-pIOld.fMemResident)");
272 0 : tree->SetAlias("RM","pI.fMemResident");
273 0 : if (fout!=0){
274 0 : TFile * f = TFile::Open(fout,"recreate");
275 0 : f->cd();
276 0 : tree->Write("AliSysInfo");
277 0 : delete f;
278 0 : }
279 0 : return tree;
280 0 : }
281 :
282 :
283 : Bool_t AliSysInfo::Contain(const char * str1, const char * str2){
284 : //
285 : //
286 : //
287 0 : TString str(str1);
288 0 : return str.Contains(str2);
289 0 : }
290 :
291 :
292 :
293 : void AliSysInfo::OpenMemStat(){
294 : //
295 : //
296 : //
297 : //USE IFDEF if MEMSTAT ENABLED
298 : // Instance()->fMemStat = TMemStatManager::GetInstance();
299 : // Instance()->fMemStat->SetAutoStamp(10000000, 10000000,1000000);
300 : // Instance()->fMemStat->Enable();
301 0 : }
302 :
303 : void AliSysInfo::CloseMemStat(){
304 : //
305 : //
306 : //
307 : //USE IFDEF if MEMSTAT ENABLED
308 : //if (Instance()->fMemStat == TMemStatManager::GetInstance()) Instance()->fMemStat->Close();
309 : //Instance()->fMemStat=0;
310 0 : }
311 :
312 :
313 :
314 : void AliSysInfo::AddCallBack(StampCallback_t callback){
315 : //
316 : // add cal back function
317 : //
318 0 : AliSysInfo *info = Instance();
319 0 : if (!info->fCallBackFunc)
320 0 : info->fCallBackFunc = new StampCallback_t[100];
321 0 : info->fCallBackFunc[info->fNCallBack]=callback;
322 0 : info->fNCallBack++;
323 0 : }
324 :
325 :
326 :
327 : TTree* AliSysInfo::Test(){
328 : //
329 : // Test example for AliSysInfo:
330 : // 1. Make huge memory leak
331 : // 2. Slow down execution
332 : /*
333 : To use the test:
334 : TTree * tree = AliSysInfo::Test();
335 : // Make alias what we set as input
336 : tree->SetAlias("deltaVMIn","(id0*100000+id1*10000+id2*1000)/1000000.")
337 : tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)");
338 : tree->SetAlias("deltaTIn","(id1+id0*10)");
339 : tree->SetAlias("deltaT","stampSec-stampOldSec");
340 : //
341 : tree->SetMarkerStyle(23); tree->SetMarkerSize(0.5);
342 : // Memory usage
343 : tree->Draw("deltaVM:deltaVMIn","Entry$>0");
344 : // or alternative
345 : tree->Draw("deltaVM:deltaVMIn","Entry$>0","prof");
346 : //
347 : // draw time usage
348 : tree->Draw("deltaT:deltaTIn","Entry$>0");
349 : */
350 : //
351 : // The delta of VM as obtained from the AliSysInfo starts to be proportional
352 : // to the input allocation after 0.12 MBy (and it is system dependent)
353 : // Bellow these limit the deltaVM can be used only in mean.
354 : // (compare first and profile histogram)
355 0 : for (Int_t id0=0; id0<5; id0++)
356 0 : for (Int_t id1=1; id1<10; id1++)
357 0 : for (Int_t id2=0; id2<20; id2++){
358 0 : new Char_t[id2*1000+id1*10000+id0*100000]; // emulate memory leak
359 0 : gSystem->Sleep(id1+id0*10); // emulate CPU usage
360 0 : AliSysInfo::AddStamp("Leak",id0,id1,id2);
361 : }
362 0 : TTree * tree = AliSysInfo::MakeTree("syswatch.log");
363 0 : return tree;
364 : }
365 :
366 : Double_t AliSysInfo::EstimateObjectSize(TObject* object){
367 : //
368 : // Estimate size of object as represented in the memory size in bytes
369 : // Warnings:
370 : // 1. Only data memebrs which are persistent are counted
371 : // 2. Local copy of the object is temporary created in memory
372 : // 3. Do not use it in standard programs, time and memory consument procedure
373 : //
374 0 : if (!object) return 0;
375 0 : TBufferFile * file = new TBufferFile(TBuffer::kWrite);
376 0 : file->WriteObject(object);
377 0 : Double_t size=file->Length();
378 0 : delete file;
379 : return size;
380 0 : }
381 :
382 :
383 : void AliSysInfo::PrintJiraTable(TTree * tree, const char *var, const char *cut, const char *format, const char *outputTable){
384 : //
385 : // Print Tree query table as a JIRA table
386 : // Generic implementation using "custom format" in the future, e.g to print html tables
387 : //
388 : /*
389 : Example:
390 : AliSysInfo::PrintJiraTable(tree, "deltaT:sname", "deltaT>0", "col=10:100", "syswatch.table");
391 : AliSysInfo::PrintJiraTable(tree, "deltaT:sname", "deltaT>0", "col=10:100", 0);
392 : AliSysInfo::PrintJiraTable(tree, "deltaT:sname:fileReadCalls:fileBytesRead/1000000", "deltaT>0", "col=10:100:25:15", 0);
393 : */
394 0 : tree->SetScanField(tree->GetEntries());
395 0 : ((TTreePlayer*)(tree->GetPlayer()))->SetScanRedirect(true);
396 0 : ((TTreePlayer*)(tree->GetPlayer()))->SetScanFileName("AliSysInfo.PrintJiraTable.tmp0");
397 0 : tree->Scan(var,cut,format);
398 0 : ((TTreePlayer*)(tree->GetPlayer()))->SetScanRedirect(0);
399 0 : gSystem->Exec("cat AliSysInfo.PrintJiraTable.tmp0 | sed s_*_\"|\"_g | grep -v \"|||\" > AliSysInfo.PrintJiraTable.tmp1");
400 0 : if (outputTable==0){
401 0 : gSystem->Exec("cat AliSysInfo.PrintJiraTable.tmp1");
402 0 : }else{
403 0 : gSystem->Exec(TString::Format("mv AliSysInfo.PrintJiraTable.tmp1 %s", outputTable).Data());
404 : }
405 :
406 0 : }
|