3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project *
5 //* ALICE Experiment at CERN, All rights reserved. *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
8 //* for The ALICE HLT Project. *
10 //* Permission to use, copy, modify and distribute this software and its *
11 //* documentation strictly for non-commercial purposes is hereby granted *
12 //* without fee, provided that the above copyright notice appears in all *
13 //* copies and that both the copyright notice and this permission notice *
14 //* appear in the supporting documentation. The authors make no claims *
15 //* about the suitability of this software for any purpose. It is *
16 //* provided "as is" without express or implied warranty. *
17 //**************************************************************************
19 /** @file AliHLTCompStatCollector.cxx
20 @author Matthias Richter
22 @brief Collector component for the component statistics information.
25 #include "AliHLTCompStatCollector.h"
27 #include "TStopwatch.h"
37 #define HLTSTAT_FOLDER_NAME "HLTstat"
38 #define HLTSTAT_FOLDER_DESC "ALICE HLT component statistics"
39 #define HLTSTAT_ENTRY_PARENT_FOLDER_NAME "parents"
40 #define HLTSTAT_ENTRY_PARENT_FOLDER_DESC "parent components"
41 #define HLTSTAT_ENTRY_PROPS_FOLDER_NAME "props"
42 #define HLTSTAT_ENTRY_PROPS_FOLDER_DESC "component properties"
43 #define HLTSTAT_ENTRY_PROPS_IDOBJ_NAME "id"
44 #define HLTSTAT_ENTRY_PROPS_IDOBJ_DESC "numerical id calculated from chain id"
46 /** ROOT macro for the implementation of ROOT specific class methods */
47 ClassImp(AliHLTCompStatCollector)
49 AliHLTCompStatCollector::AliHLTCompStatCollector()
65 fpInputBlockCountArray(NULL),
66 fpTotalInputSizeArray(NULL),
67 fpOutputBlockCountArray(NULL),
68 fpTotalOutputSizeArray(NULL)
69 , fSizeEstimator(1000)
70 , fMode(kPublishObjects)
73 , fLastTime(time(NULL))
77 // see header file for class documentation
79 // refer to README to build package
81 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
84 AliHLTCompStatCollector::~AliHLTCompStatCollector()
86 // see header file for class documentation
90 void AliHLTCompStatCollector::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
92 // see header file for class documentation
93 list.push_back(kAliHLTDataTypeComponentStatistics);
96 AliHLTComponentDataType AliHLTCompStatCollector::GetOutputDataType()
98 // see header file for class documentation
99 return kAliHLTMultipleDataType;
102 int AliHLTCompStatCollector::GetOutputDataTypes(AliHLTComponentDataTypeList& tgtList)
104 // see header file for class documentation
106 tgtList.push_back(kAliHLTDataTypeHistogram);
107 tgtList.push_back(kAliHLTDataTypeTTree);
108 return tgtList.size();
111 void AliHLTCompStatCollector::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
113 // see header file for class documentation
114 constBase=fSizeEstimator;
115 inputMultiplier=100.0;
118 int AliHLTCompStatCollector::DoInit( int argc, const char** argv )
120 // see header file for class documentation
124 for (int i=0; i<argc && iResult>=0; i++) {
126 if (argument.IsNull()) continue;
129 if (argument.CompareTo("-file")==0) {
130 if ((bMissingParam=(++i>=argc))) break;
135 } else if (argument.CompareTo("-modulo")==0) {
136 if ((bMissingParam=(++i>=argc))) break;
137 TString param=argv[i];
138 if (param.IsDigit()) {
139 fEventModulo=param.Atoi();
141 HLTError("expecting number as parameter for option %s", argument.Data());
146 } else if (argument.CompareTo("-period")==0) {
147 if ((bMissingParam=(++i>=argc))) break;
148 TString param=argv[i];
149 if (param.IsDigit()) {
150 fPeriod=param.Atoi();
152 HLTError("expecting number as parameter for option %s", argument.Data());
157 } else if (argument.CompareTo("-publish")==0) {
158 if ((bMissingParam=(++i>=argc))) break;
159 TString param=argv[i];
160 if (param.IsDigit()) {
161 if (param.Atoi()==1) fMode|=kPublishObjects;
162 else if (param.Atoi()==0) fMode&=~kPublishObjects;
164 HLTError("expecting 0 or 1 as parameter for option %s", argument.Data());
168 HLTError("expecting number as parameter for option %s", argument.Data());
172 HLTError("unknown argument %s", argument.Data());
177 HLTError("missing parameter for argument %s", argument.Data());
182 fpLevelArray=new UInt_t[fArraySize];
183 fpSpecArray=new UInt_t[fArraySize];
184 fpBlockNoArray=new UInt_t[fArraySize];
185 fpIdArray=new UInt_t[fArraySize];
186 fpTimeArray=new UInt_t[fArraySize];
187 fpCTimeArray=new UInt_t[fArraySize];
188 fpInputBlockCountArray=new UInt_t[fArraySize];
189 fpTotalInputSizeArray=new UInt_t[fArraySize];
190 fpOutputBlockCountArray=new UInt_t[fArraySize];
191 fpTotalOutputSizeArray=new UInt_t[fArraySize];
193 fpStatTree=new TTree("CompStat", "HLT component statistics");
195 fpStatTree->SetDirectory(0);
196 fpStatTree->Branch("cycleTime", &fCycleTime, "cycleTime/F");
197 fpStatTree->Branch("nofSets", &fNofSets, "nofSets/I");
198 fpStatTree->Branch("Level", fpLevelArray, "Level[nofSets]/i");
199 fpStatTree->Branch("Specification", fpSpecArray, "Specification[nofSets]/i");
200 fpStatTree->Branch("BlockNo", fpBlockNoArray, "BlockNo[nofSets]/i");
201 fpStatTree->Branch("Id", fpIdArray, "Id[nofSets]/i");
202 fpStatTree->Branch("Time", fpTimeArray, "Time[nofSets]/i");
203 fpStatTree->Branch("CTime", fpCTimeArray, "CTime[nofSets]/i");
204 fpStatTree->Branch("InputBlockCount", fpInputBlockCountArray, "InputBlockCount[nofSets]/i");
205 fpStatTree->Branch("TotalInputSize", fpTotalInputSizeArray, "TotalInputSize[nofSets]/i");
206 fpStatTree->Branch("OutputBlockCount", fpOutputBlockCountArray, "OutputBlockCount[nofSets]/i");
207 fpStatTree->Branch("TotalOutputSize", fpTotalOutputSizeArray, "TotalOutputSize[nofSets]/i");
211 if (!fFileName.empty()) {
212 fFile=new TFile(fFileName.c_str(), "RECREATE");
217 int AliHLTCompStatCollector::DoDeinit( )
219 // see header file for class documentation
230 int AliHLTCompStatCollector::DoEvent( const AliHLTComponentEventData& /*evtData*/, AliHLTComponentTriggerData& /*trigData*/)
232 // see header file for class documentation
235 AliHLTUInt32_t eventType=gkAliEventTypeUnknown;
236 IsDataEvent(&eventType);
238 ResetFillingVariables();
240 fCycleTime=fpTimer->RealTime()*1000000;
243 bool bEmbeddedTree=false;
244 bool bFolderCreated=false;
245 if ((bFolderCreated=(fpFolder==NULL))) {
246 fpFolder=new TFolder(HLTSTAT_FOLDER_NAME, HLTSTAT_FOLDER_DESC);
247 if (bEmbeddedTree) fpFolder->Add(fpStatTree);
249 if (!fpFolder) return -ENOMEM;
250 vector<TFolder*> newFolders;
252 for (const AliHLTComponentBlockData* pBlock=GetFirstInputBlock(kAliHLTDataTypeComponentTable);
253 pBlock && iResult>=0;
254 pBlock=GetNextInputBlock()) {
255 string chainId, compId, compArgs;
256 vector<AliHLTUInt32_t> parents;
257 iResult=ExtractComponentTableEntry((const AliHLTUInt8_t*)pBlock->fPtr, pBlock->fSize,
258 chainId, compId, compArgs,
261 HLTDebug("%s(%s) 0x%08x", chainId.c_str(), compId.c_str(), pBlock->fSpecification);
263 TFolder* pEntry=NULL;
264 if ((pObj=fpFolder->FindObjectAny(chainId.c_str()))!=NULL &&
265 (pEntry=dynamic_cast<TFolder*>(pObj))!=NULL ) {
268 HLTError("entry %s exists in folder, but is not a sub-folder", chainId.c_str());
269 } else if (chainId.size()>0) {
270 pEntry=new TFolder(chainId.c_str(), chainId.c_str());
273 TFolder* pProps=pEntry->AddFolder(HLTSTAT_ENTRY_PROPS_FOLDER_NAME, HLTSTAT_ENTRY_PROPS_FOLDER_DESC);
275 pProps->Add(new TObjString(compId.c_str()));
276 if (!compArgs.empty())
277 pProps->Add(new TObjString(compArgs.c_str()));
278 TNamed* pCRC=new TNamed(HLTSTAT_ENTRY_PROPS_IDOBJ_NAME, HLTSTAT_ENTRY_PROPS_IDOBJ_DESC);
280 pCRC->SetUniqueID(pBlock->fSpecification);
284 TFolder* pParents=pEntry->AddFolder(HLTSTAT_ENTRY_PARENT_FOLDER_NAME, HLTSTAT_ENTRY_PARENT_FOLDER_DESC);
286 for (vector<AliHLTUInt32_t>::iterator parent=parents.begin();
287 parent!=parents.end(); parent++) {
288 TString name; name.Form("0x%08x", *parent);
289 pParents->Add(new TObjString(name));
292 if (parents.size()==0) {
293 newFolders.push_back(pEntry);
295 vector<TFolder*>::iterator iter=newFolders.begin();
296 vector<AliHLTUInt32_t>::iterator parent=parents.begin();
297 while (iter!=newFolders.end() && parent!=parents.end()) {
298 TObject* idobj=(*iter)->FindObjectAny(HLTSTAT_ENTRY_PROPS_IDOBJ_NAME);
299 AliHLTUInt32_t crcid=0;
300 if (idobj) crcid=idobj->GetUniqueID();
301 HLTDebug("check: %s 0x%08x", (*iter)->GetName(), crcid);
302 if (idobj && crcid==*parent) break;
303 if ((++parent!=parents.end())) continue;
304 parent=parents.begin();
307 newFolders.insert(iter,pEntry);
311 HLTError("missing chain id for table entry 0x%08x (%p %d), skipping ...", pBlock->fSpecification, pBlock->fPtr, pBlock->fSize);
313 } else if (iResult!=0) {
314 HLTError("extraction of table entry 0x%08x (%p %d) failed with %d", pBlock->fSpecification, pBlock->fPtr, pBlock->fSize, iResult);
319 if (newFolders.size()>0) {
320 vector<TFolder*> revert;
321 vector<TFolder*>::iterator iter=newFolders.begin();
322 while (iter!=newFolders.end()) {
323 revert.insert(revert.begin(), *iter);
324 HLTDebug("%s", (*iter)->GetName());
328 newFolders.assign(revert.begin(), revert.end());
330 vector<TFolder*>::iterator publisher=newFolders.begin();
331 while (publisher!=newFolders.end()) {
333 HLTDebug("checking %s for parents", (*publisher)->GetName());
334 TFolder* propsFolder=dynamic_cast<TFolder*>((*publisher)->FindObject(HLTSTAT_ENTRY_PROPS_FOLDER_NAME));
337 if (propsFolder) idobj=propsFolder->FindObject(HLTSTAT_ENTRY_PROPS_IDOBJ_NAME);
339 AliHLTUInt32_t crcid=idobj->GetUniqueID();
340 TString idstr; idstr.Form("0x%08x", crcid);
342 for (vector<TFolder*>::iterator consumer=publisher+1;
343 consumer!=newFolders.end(); consumer++) {
344 HLTDebug(" checking %s", (*consumer)->GetName());
345 TFolder* parentFolder=dynamic_cast<TFolder*>((*consumer)->FindObject(HLTSTAT_ENTRY_PARENT_FOLDER_NAME));
346 assert(parentFolder);
348 TIter entries(parentFolder->GetListOfFolders());
349 while (TObject* entry=entries.Next())
351 Bool_t foo; foo=kTRUE;// only to avoid warning in non-debug compile
352 HLTDebug(" searching %s in %s: %s", idstr.Data(), (*consumer)->GetName(), entry->GetName());
354 TObject* parent=parentFolder->FindObjectAny(idstr);
356 parentFolder->Add(*publisher);
357 parentFolder->Remove(parent);
363 if (bRemove) publisher=newFolders.erase(publisher);
367 for (publisher=newFolders.begin();
368 publisher!=newFolders.end(); publisher++) {
369 RemoveRecurrence(*publisher);
370 fpFolder->Add(*publisher);
375 for (const AliHLTComponentBlockData* pBlock=GetFirstInputBlock(kAliHLTDataTypeComponentStatistics);
376 pBlock && iResult>=0;
377 pBlock=GetNextInputBlock(), blockNo++) {
378 unsigned int current=fPosition;
379 iResult=FillVariablesSorted(pBlock->fPtr, pBlock->fSize);
380 for (; current<fPosition; current++) {
381 fpSpecArray[current]=pBlock->fSpecification;
382 fpBlockNoArray[current]=blockNo;
384 // indicate availability of component statistic block
388 int totalOutputSize=0;
393 // init the timer for the next cycle
394 if (!fpTimer) fpTimer=new TStopwatch;
401 if (eventType==gkAliEventTypeEndOfRun ||
402 (iResult>=0 && CheckPeriod())) {
404 // publish objects to component output
405 if ((fMode&kPublishObjects)!=0) {
406 if (!bEmbeddedTree) {
407 iResult=PushBack(fpStatTree, kAliHLTDataTypeTTree|kAliHLTDataOriginOut);
408 totalOutputSize+=GetLastObjectSize();
410 iResult=PushBack(fpFolder, kAliHLTDataTypeTObject|kAliHLTDataOriginOut);
411 totalOutputSize+=GetLastObjectSize();
414 // save objects to file
415 if ((fMode&kSaveObjects)!=0 && fFile!=NULL) {
416 HLTDebug("saving objects to file %s", fFileName.c_str());
418 if (!bEmbeddedTree) {
419 fpStatTree->Write("", TObject::kOverwrite);
421 fpFolder->Write("", TObject::kOverwrite);
425 if (iResult==-ENOSPC) {
426 fSizeEstimator+=totalOutputSize;
429 if (iResult>0) iResult=0;
433 void AliHLTCompStatCollector::ResetFillingVariables()
435 // see header file for class documentation
439 memset(fpLevelArray, 0, sizeof(UInt_t)*fArraySize);
440 memset(fpSpecArray, 0, sizeof(UInt_t)*fArraySize);
441 memset(fpBlockNoArray, 0, sizeof(UInt_t)*fArraySize);
442 memset(fpIdArray, 0, sizeof(UInt_t)*fArraySize);
443 memset(fpTimeArray, 0, sizeof(UInt_t)*fArraySize);
444 memset(fpCTimeArray, 0, sizeof(UInt_t)*fArraySize);
445 memset(fpInputBlockCountArray, 0, sizeof(UInt_t)*fArraySize);
446 memset(fpTotalInputSizeArray, 0, sizeof(UInt_t)*fArraySize);
447 memset(fpOutputBlockCountArray, 0, sizeof(UInt_t)*fArraySize);
448 memset(fpTotalOutputSizeArray, 0, sizeof(UInt_t)*fArraySize);
451 int AliHLTCompStatCollector::FillVariablesSorted(void* ptr, int size)
453 // see header file for class documentation
455 if (size%sizeof(AliHLTComponentStatistics)) {
456 HLTError("data block is not aligned to the size of the AliHLTComponentStatistics struct");
459 AliHLTComponentStatistics* pStat=reinterpret_cast<AliHLTComponentStatistics*>(ptr);
460 UInt_t nofStats=size/sizeof(AliHLTComponentStatistics);
461 vector<int> indexList;
463 for (i=0; i<nofStats; i++) {
464 vector<int>::iterator element=indexList.begin();
465 for (; element!=indexList.end(); element++) {
466 if (pStat[i].fLevel>pStat[*element].fLevel) {
470 indexList.insert(element, i);
474 for (vector<int>::iterator element=indexList.begin();
475 element!=indexList.end();
478 fpLevelArray[i]=pStat[*element].fLevel;
479 fpIdArray[i]=pStat[*element].fId;
480 fpTimeArray[i]=pStat[*element].fTime;
481 fpCTimeArray[i]=pStat[*element].fCTime;
482 fpInputBlockCountArray[i]=pStat[*element].fInputBlockCount;
483 fpTotalInputSizeArray[i]=pStat[*element].fTotalInputSize;
484 fpOutputBlockCountArray[i]=pStat[*element].fOutputBlockCount;
485 fpTotalOutputSizeArray[i]=pStat[*element].fTotalOutputSize;
487 // TODO: dynamically grow arrays with placement new
492 HLTWarning("too little space in branch variables to fill %d statistics blocks, available %d at position %d", i, fArraySize, fPosition);
493 fPosition=fArraySize;
501 void AliHLTCompStatCollector::ClearAll()
503 // see header file for class documentation
504 if (fpTimer) delete fpTimer; fpTimer=NULL;
505 if (fpFolder) delete fpFolder; fpFolder=NULL;
506 if (fpStatTree) delete fpStatTree; fpStatTree=NULL;
507 if (fpLevelArray) delete fpLevelArray; fpLevelArray=NULL;
508 if (fpSpecArray) delete fpSpecArray; fpSpecArray=NULL;
509 if (fpBlockNoArray) delete fpBlockNoArray; fpBlockNoArray=NULL;
510 if (fpIdArray) delete fpIdArray; fpIdArray=NULL;
511 if (fpTimeArray) delete fpTimeArray; fpTimeArray=NULL;
512 if (fpCTimeArray) delete fpCTimeArray; fpCTimeArray=NULL;
513 if (fpInputBlockCountArray) delete fpInputBlockCountArray; fpInputBlockCountArray=NULL;
514 if (fpTotalInputSizeArray) delete fpTotalInputSizeArray; fpTotalInputSizeArray=NULL;
515 if (fpOutputBlockCountArray) delete fpOutputBlockCountArray; fpOutputBlockCountArray=NULL;
516 if (fpTotalOutputSizeArray) delete fpTotalOutputSizeArray; fpTotalOutputSizeArray=NULL;
519 int AliHLTCompStatCollector::RemoveRecurrence(TFolder* pRoot) const
521 // see header file for class documentation
523 if (!pRoot) return -EINVAL;
524 TFolder* parentFolder=dynamic_cast<TFolder*>(pRoot->FindObject(HLTSTAT_ENTRY_PARENT_FOLDER_NAME));
525 assert(parentFolder);
526 vector<TFolder*> listRemove;
528 TIter entries(parentFolder->GetListOfFolders());
531 while ((obj=entries.Next())!=NULL && (entry=dynamic_cast<TFolder*>(obj))!=NULL) {
532 TString name=entry->GetName();
533 HLTDebug("checking %s for recurrence", name.Data());
534 TIter tokens(parentFolder->GetListOfFolders());
536 while ((obj=tokens.Next())!=NULL && (token=dynamic_cast<TFolder*>(obj))!=NULL) {
537 if (name.CompareTo(token->GetName())==0) continue;
538 if ((obj=token->FindObjectAny(name))!=NULL) {
539 listRemove.push_back(entry);
540 HLTDebug("found recurrence in %s", token->GetName());
543 HLTDebug("no recurrence found in %s", token->GetName());
546 RemoveRecurrence(entry);
548 for (vector<TFolder*>::iterator removeElement=listRemove.begin();
549 removeElement!=listRemove.end(); removeElement++) {
550 parentFolder->Remove(*removeElement);
557 bool AliHLTCompStatCollector::CheckPeriod(bool bUpdate)
559 // see header file for class documentation
561 if (fEventModulo>0) {
562 if ((result=((GetEventCount()+1)%fEventModulo)==0)) {
567 if ((result=((difftime(time(NULL), fLastTime)>(double)fPeriod))) &&
569 fLastTime=time(NULL);