]>
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> |
85 | #include "AliLog.h" | |
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 | |
98 | ClassImp(AliSysInfo) | |
99 | ||
100 | AliSysInfo* AliSysInfo::fInstance=0; | |
101 | ||
102 | AliSysInfo::AliSysInfo(): | |
103 | TObject(), | |
104 | fSysWatch(0), | |
6efecea1 | 105 | fTimer(0), |
d1d8b044 | 106 | fMemStat(0), |
107 | fCallBackFunc(0), | |
108 | fNCallBack(0) | |
0e8bc704 | 109 | { |
110 | fTimer = new TStopwatch; | |
111 | fSysWatch = new fstream("syswatch.log", ios_base::out|ios_base::trunc); | |
6efecea1 | 112 | |
ab557934 | 113 | //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 | 114 | |
115 | ||
116 | (*fSysWatch) <<"hname"<<"/C:" // hname - hostname | |
117 | <<"sname"<<"/C:" // stamp name | |
6efecea1 | 118 | <<"id0"<<"/I:" // 0 id |
119 | <<"id1"<<"/I:" // 1 id | |
120 | <<"id2"<<"/I:" // 1 id | |
ab557934 | 121 | <<"first"<<"/D:" // first stamp |
0e8bc704 | 122 | // |
ab557934 | 123 | <<"stampSec"<<"/D:" // time - time stamp in seconds |
124 | <<"mi.fMemUsed"<<"/D:" // system info | |
125 | <<"mi.fSwapUsed"<<"/D:" // | |
126 | <<"cI.fUser"<<"/D:" // | |
127 | <<"cI.fSys"<<"/D:" // | |
0e8bc704 | 128 | // |
ab557934 | 129 | <<"pI.fMemResident"<<"/D:" // process info |
130 | <<"pI.fMemVirtual"<<"/D:" // | |
131 | <<"pI.fCpuUser"<<"/D:" // | |
132 | <<"pI.fCpuSys"<<"/D:" // | |
0e8bc704 | 133 | // |
ab557934 | 134 | <<"stampOldSec"<<"/D:" // time - time stamp in seconds |
135 | <<"miOld.fMemUsed"<<"/D:" // system info - previous | |
136 | <<"miOld.fSwapUsed"<<"/D:" // | |
137 | <<"cIOld.fUser"<<"/D:" // | |
138 | <<"cIOld.fSys"<<"/D:" // | |
0e8bc704 | 139 | // |
ab557934 | 140 | <<"pIOld.fMemResident"<<"/D:" // process info -previous |
141 | <<"pIOld.fMemVirtual"<<"/D:" // | |
142 | <<"pIOld.fCpuUser"<<"/D:" // | |
a8bc7397 | 143 | <<"pIOld.fCpuSys"<<"/D:" // |
144 | // | |
145 | <<"fileBytesRead"<<"/D:" // file IO information | |
146 | <<"fileBytesWritten"<<"/D:" // | |
147 | <<"fileCounter"<<"/D:" // | |
148 | <<"fileReadCalls"<<"/D" // | |
0e8bc704 | 149 | << endl; |
150 | ||
151 | } | |
152 | ||
153 | ||
154 | ||
155 | ||
156 | AliSysInfo * AliSysInfo::Instance(){ | |
157 | // | |
158 | // | |
159 | // | |
160 | if (!fInstance){ | |
161 | fInstance = new AliSysInfo; | |
162 | } | |
163 | return fInstance; | |
164 | } | |
165 | ||
166 | ||
6efecea1 | 167 | void AliSysInfo::AddStamp(const char *sname, Int_t id0, Int_t id1, Int_t id2){ |
0e8bc704 | 168 | // |
169 | // | |
170 | // | |
0e8bc704 | 171 | // |
0e8bc704 | 172 | TTimeStamp stamp; |
173 | CpuInfo_t cpuInfo; | |
174 | MemInfo_t memInfo; | |
175 | ProcInfo_t procInfo; | |
176 | gSystem->GetCpuInfo(&cpuInfo, 10); | |
177 | gSystem->GetMemInfo(&memInfo); | |
178 | gSystem->GetProcInfo(&procInfo); | |
ab557934 | 179 | // procInfo.fMemVirtual/=1024; //size in MBy |
180 | //procInfo.fMemResident/=1024; //size in MBy | |
d1d8b044 | 181 | |
0e8bc704 | 182 | const char * hname = gSystem->HostName(); |
183 | ||
184 | static Int_t entry=0; | |
ab557934 | 185 | static Double_t first=stamp.GetSec()+stamp.GetNanoSec()/1000000000.; |
0e8bc704 | 186 | // |
187 | static TTimeStamp stampOld; | |
188 | static CpuInfo_t cpuInfoOld; | |
189 | static MemInfo_t memInfoOld; | |
190 | static ProcInfo_t procInfoOld; | |
a8bc7397 | 191 | Double_t fileBytesRead = TFile::GetFileBytesRead(); |
192 | Double_t fileBytesWritten = TFile::GetFileBytesWritten(); | |
193 | Double_t fileCounter = TFile::GetFileCounter(); | |
194 | Double_t fileReadCalls = TFile::GetFileReadCalls(); | |
0e8bc704 | 195 | |
196 | ||
ab557934 | 197 | (*(Instance()->fSysWatch)) |
198 | << hname <<"\t" // hname - hostname | |
199 | << sname <<"\t" // stamp name | |
200 | << id0 <<"\t" | |
201 | << id1 <<"\t" | |
202 | << id2 <<"\t" | |
203 | <<setprecision(15)<< first <<"\t" // first stamp | |
0e8bc704 | 204 | // |
ab557934 | 205 | <<setprecision(15)<< stamp.GetSec()+stamp.GetNanoSec()/1000000000.<<"\t" // time - time stamp in seconds |
206 | << memInfo.fMemUsed<<"\t" // system info | |
207 | << memInfo.fSwapUsed<<"\t" // | |
208 | << cpuInfo.fUser <<"\t" // | |
209 | << cpuInfo.fSys <<"\t" // | |
210 | // | |
211 | <<setprecision(15)<< procInfo.fMemResident/1024.<<"\t" // process info | |
212 | <<setprecision(15)<< procInfo.fMemVirtual/1024.<<"\t" // | |
213 | << procInfo.fCpuUser<<"\t" // | |
214 | << procInfo.fCpuSys<<"\t" // | |
215 | // | |
216 | <<setprecision(15)<< stampOld.GetSec()+stampOld.GetNanoSec()/1000000000.<<"\t" // time - time stamp in seconds | |
217 | << memInfoOld.fMemUsed<<"\t" // system info - previous | |
218 | << memInfoOld.fSwapUsed<<"\t" // | |
219 | << cpuInfoOld.fUser <<"\t" // | |
220 | << cpuInfoOld.fSys <<"\t" // | |
221 | // | |
222 | <<setprecision(15)<< procInfoOld.fMemResident/1024.<<"\t" // process info -previous | |
223 | <<setprecision(15)<< procInfoOld.fMemVirtual/1024.<<"\t" // | |
224 | << procInfoOld.fCpuUser<<"\t" // | |
225 | << procInfoOld.fCpuSys<<"\t" // | |
a8bc7397 | 226 | // |
227 | <<fileBytesRead<<"\t" // file IO information | |
228 | <<fileBytesWritten<<"\t" // | |
229 | <<fileCounter<<"\t" // | |
230 | <<fileReadCalls<<"\t" // | |
ab557934 | 231 | << endl; |
232 | ||
0e8bc704 | 233 | stampOld = stamp; |
234 | cpuInfoOld = cpuInfo; | |
235 | memInfoOld = memInfo; | |
6efecea1 | 236 | procInfoOld= procInfo; |
237 | ||
238 | // if (fInstance->fMemStat) fInstance->fMemStat->AddStamps(sname); | |
d1d8b044 | 239 | for (Int_t icallback=0; icallback<Instance()->fNCallBack; icallback++){ |
240 | Instance()->fCallBackFunc[icallback](sname); | |
241 | } | |
0e8bc704 | 242 | entry++; |
243 | } | |
244 | ||
245 | ||
246 | TTree * AliSysInfo::MakeTree(const char *lname){ | |
247 | // char * lname = "syswatch.log" | |
248 | TTree * tree = new TTree; | |
249 | tree->ReadFile(lname); | |
250 | tree->SetAlias("deltaT","stampSec-stampOldSec"); | |
6efecea1 | 251 | tree->SetAlias("T","stampSec-first"); |
d1d8b044 | 252 | tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)"); |
253 | tree->SetAlias("VM","pI.fMemVirtual"); | |
0e8bc704 | 254 | return tree; |
255 | } | |
256 | ||
6efecea1 | 257 | |
258 | Bool_t AliSysInfo::Contain(const char * str1, const char * str2){ | |
259 | // | |
260 | // | |
261 | // | |
262 | TString str(str1); | |
263 | return str.Contains(str2); | |
264 | } | |
265 | ||
266 | ||
267 | ||
268 | void AliSysInfo::OpenMemStat(){ | |
269 | // | |
270 | // | |
271 | // | |
272 | //USE IFDEF if MEMSTAT ENABLED | |
273 | // Instance()->fMemStat = TMemStatManager::GetInstance(); | |
274 | // Instance()->fMemStat->SetAutoStamp(10000000, 10000000,1000000); | |
275 | // Instance()->fMemStat->Enable(); | |
276 | } | |
277 | ||
278 | void AliSysInfo::CloseMemStat(){ | |
279 | // | |
280 | // | |
281 | // | |
282 | //USE IFDEF if MEMSTAT ENABLED | |
283 | //if (Instance()->fMemStat == TMemStatManager::GetInstance()) Instance()->fMemStat->Close(); | |
284 | //Instance()->fMemStat=0; | |
285 | } | |
d1d8b044 | 286 | |
287 | ||
288 | ||
289 | void AliSysInfo::AddCallBack(StampCallback_t callback){ | |
290 | // | |
291 | // add cal back function | |
292 | // | |
293 | AliSysInfo *info = Instance(); | |
294 | if (!info->fCallBackFunc) | |
295 | info->fCallBackFunc = new StampCallback_t[100]; | |
296 | info->fCallBackFunc[info->fNCallBack]=callback; | |
297 | info->fNCallBack++; | |
298 | } | |
ab557934 | 299 | |
300 | ||
301 | ||
302 | TTree* AliSysInfo::Test(){ | |
303 | // | |
304 | // Test example for AliSysInfo: | |
305 | // 1. Make huge memory leak | |
306 | // 2. Slow down execution | |
307 | /* | |
308 | To use the test: | |
309 | TTree * tree = AliSysInfo::Test(); | |
310 | // Make alias what we set as input | |
311 | tree->SetAlias("deltaVMIn","(id0*100000+id1*10000+id2*1000)/1000000.") | |
312 | tree->SetAlias("deltaVM","(pI.fMemVirtual-pIOld.fMemVirtual)"); | |
313 | tree->SetAlias("deltaTIn","(id1+id0*10)"); | |
314 | tree->SetAlias("deltaT","stampSec-stampOldSec"); | |
315 | // | |
316 | tree->SetMarkerStyle(23); tree->SetMarkerSize(0.5); | |
317 | // Memory usage | |
318 | tree->Draw("deltaVM:deltaVMIn","Entry$>0"); | |
319 | // or alternative | |
320 | tree->Draw("deltaVM:deltaVMIn","Entry$>0","prof"); | |
321 | // | |
322 | // draw time usage | |
323 | tree->Draw("deltaT:deltaTIn","Entry$>0"); | |
324 | */ | |
325 | // | |
326 | // The delta of VM as obtained from the AliSysInfo starts to be proportional | |
327 | // to the input allocation after 0.12 MBy (and it is system dependent) | |
328 | // Bellow these limit the deltaVM can be used only in mean. | |
329 | // (compare first and profile histogram) | |
330 | for (Int_t id0=0; id0<5; id0++) | |
331 | for (Int_t id1=1; id1<10; id1++) | |
332 | for (Int_t id2=0; id2<20; id2++){ | |
333 | new Char_t[id2*1000+id1*10000+id0*100000]; // emulate memory leak | |
334 | gSystem->Sleep(id1+id0*10); // emulate CPU usage | |
335 | AliSysInfo::AddStamp("Leak",id0,id1,id2); | |
336 | } | |
337 | TTree * tree = AliSysInfo::MakeTree("syswatch.log"); | |
338 | return tree; | |
339 | } | |
cd507f9c | 340 | |
341 | Double_t AliSysInfo::EstimateObjectSize(TObject* object){ | |
342 | // | |
343 | // Estimate size of object as represented in the memory size in bytes | |
344 | // Warnings: | |
345 | // 1. Only data memebrs which are persistent are counted | |
346 | // 2. Local copy of the object is temporary created in memory | |
347 | // 3. Do not use it in standard programs, time and memory consument procedure | |
348 | // | |
349 | if (!object) return 0; | |
350 | TBufferFile * file = new TBufferFile(TBuffer::kWrite); | |
351 | file->WriteObject(object); | |
352 | Double_t size=file->Length(); | |
353 | delete file; | |
354 | return size; | |
355 | } |