]>
Commit | Line | Data |
---|---|---|
0e8bc704 | 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 | ||
6efecea1 | 17 | // |
18 | // Origin: marian.ivanov@cern.ch | |
19 | // | |
20 | // Make a log file for the CPU and Memory usage | |
ab557934 | 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 | // | |
6efecea1 | 67 | // |
ab557934 | 68 | // |
69 | // | |
70 | // The typical usage in the AliRoot code: | |
6efecea1 | 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 | ||
0e8bc704 | 84 | #include <Riostream.h> |
5d170a72 | 85 | //#include "AliLog.h" |
0e8bc704 | 86 | #include "TStopwatch.h" |
87 | #include "TSystem.h" | |
88 | #include "TTree.h" | |
a8bc7397 | 89 | #include "TFile.h" |
0e8bc704 | 90 | |
91 | #include "TTimeStamp.h" | |
92 | #include "AliSysInfo.h" | |
cd507f9c | 93 | #include "TBufferFile.h" |
0e8bc704 | 94 | |
6efecea1 | 95 | //#include "TMemStatManager.h" //USE IFDEF |
96 | ||
0e8bc704 | 97 | |
66b0310c | 98 | using std::endl; |
99 | using std::cout; | |
100 | using std::ios_base; | |
101 | using std::setprecision; | |
0e8bc704 | 102 | ClassImp(AliSysInfo) |
103 | ||
104 | AliSysInfo* AliSysInfo::fInstance=0; | |
3b365312 | 105 | Bool_t AliSysInfo::fgVerbose = kTRUE; |
0e8bc704 | 106 | |
107 | AliSysInfo::AliSysInfo(): | |
108 | TObject(), | |
109 | fSysWatch(0), | |
6efecea1 | 110 | fTimer(0), |
d1d8b044 | 111 | fMemStat(0), |
112 | fCallBackFunc(0), | |
113 | fNCallBack(0) | |
0e8bc704 | 114 | { |
115 | fTimer = new TStopwatch; | |
116 | fSysWatch = new fstream("syswatch.log", ios_base::out|ios_base::trunc); | |
6efecea1 | 117 | |
ab557934 | 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 |
0e8bc704 | 119 | |
120 | ||
121 | (*fSysWatch) <<"hname"<<"/C:" // hname - hostname | |
122 | <<"sname"<<"/C:" // stamp name | |
6efecea1 | 123 | <<"id0"<<"/I:" // 0 id |
124 | <<"id1"<<"/I:" // 1 id | |
125 | <<"id2"<<"/I:" // 1 id | |
02098121 | 126 | <<"id3"<<"/I:" // 1 id |
ab557934 | 127 | <<"first"<<"/D:" // first stamp |
0e8bc704 | 128 | // |
ab557934 | 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:" // | |
62d0bd6a | 134 | <<"cI.fLoad1m"<<"/D:" // |
135 | <<"cI.fLoad5m"<<"/D:" // | |
136 | <<"cI.fLoad15m"<<"/D:" // | |
0e8bc704 | 137 | // |
ab557934 | 138 | <<"pI.fMemResident"<<"/D:" // process info |
139 | <<"pI.fMemVirtual"<<"/D:" // | |
140 | <<"pI.fCpuUser"<<"/D:" // | |
141 | <<"pI.fCpuSys"<<"/D:" // | |
0e8bc704 | 142 | // |
ab557934 | 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:" // | |
0e8bc704 | 148 | // |
ab557934 | 149 | <<"pIOld.fMemResident"<<"/D:" // process info -previous |
150 | <<"pIOld.fMemVirtual"<<"/D:" // | |
151 | <<"pIOld.fCpuUser"<<"/D:" // | |
a8bc7397 | 152 | <<"pIOld.fCpuSys"<<"/D:" // |
153 | // | |
154 | <<"fileBytesRead"<<"/D:" // file IO information | |
155 | <<"fileBytesWritten"<<"/D:" // | |
156 | <<"fileCounter"<<"/D:" // | |
157 | <<"fileReadCalls"<<"/D" // | |
0e8bc704 | 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 | ||
02098121 | 176 | void AliSysInfo::AddStamp(const char *sname, Int_t id0, Int_t id1, Int_t id2, Int_t id3){ |
0e8bc704 | 177 | // |
178 | // | |
1ce2c63c | 179 | if (!fgVerbose) return; |
0e8bc704 | 180 | // |
0e8bc704 | 181 | // |
0e8bc704 | 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); | |
ab557934 | 189 | // procInfo.fMemVirtual/=1024; //size in MBy |
190 | //procInfo.fMemResident/=1024; //size in MBy | |
d1d8b044 | 191 | |
0e8bc704 | 192 | const char * hname = gSystem->HostName(); |
193 | ||
194 | static Int_t entry=0; | |
ab557934 | 195 | static Double_t first=stamp.GetSec()+stamp.GetNanoSec()/1000000000.; |
0e8bc704 | 196 | // |
197 | static TTimeStamp stampOld; | |
198 | static CpuInfo_t cpuInfoOld; | |
199 | static MemInfo_t memInfoOld; | |
200 | static ProcInfo_t procInfoOld; | |
a8bc7397 | 201 | Double_t fileBytesRead = TFile::GetFileBytesRead(); |
202 | Double_t fileBytesWritten = TFile::GetFileBytesWritten(); | |
203 | Double_t fileCounter = TFile::GetFileCounter(); | |
204 | Double_t fileReadCalls = TFile::GetFileReadCalls(); | |
0e8bc704 | 205 | |
206 | ||
ab557934 | 207 | (*(Instance()->fSysWatch)) |
208 | << hname <<"\t" // hname - hostname | |
209 | << sname <<"\t" // stamp name | |
210 | << id0 <<"\t" | |
211 | << id1 <<"\t" | |
212 | << id2 <<"\t" | |
02098121 | 213 | << id3 <<"\t" |
ab557934 | 214 | <<setprecision(15)<< first <<"\t" // first stamp |
0e8bc704 | 215 | // |
ab557934 | 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" // | |
62d0bd6a | 221 | << cpuInfo.fLoad1m <<"\t" // |
222 | << cpuInfo.fLoad5m <<"\t" // | |
223 | << cpuInfo.fLoad15m <<"\t" // | |
ab557934 | 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" // | |
a8bc7397 | 240 | // |
241 | <<fileBytesRead<<"\t" // file IO information | |
242 | <<fileBytesWritten<<"\t" // | |
243 | <<fileCounter<<"\t" // | |
244 | <<fileReadCalls<<"\t" // | |
ab557934 | 245 | << endl; |
246 | ||
0e8bc704 | 247 | stampOld = stamp; |
248 | cpuInfoOld = cpuInfo; | |
249 | memInfoOld = memInfo; | |
6efecea1 | 250 | procInfoOld= procInfo; |
251 | ||
252 | // if (fInstance->fMemStat) fInstance->fMemStat->AddStamps(sname); | |
d1d8b044 | 253 | for (Int_t icallback=0; icallback<Instance()->fNCallBack; icallback++){ |
254 | Instance()->fCallBackFunc[icallback](sname); | |
255 | } | |
0e8bc704 | 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"); | |
6efecea1 | 265 | tree->SetAlias("T","stampSec-first"); |
d1d8b044 | 266 | tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)"); |
267 | tree->SetAlias("VM","pI.fMemVirtual"); | |
0e8bc704 | 268 | return tree; |
269 | } | |
270 | ||
6efecea1 | 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 | } | |
d1d8b044 | 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 | } | |
ab557934 | 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 | } | |
cd507f9c | 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 | } |