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