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 fpNormalizedInputSizeArray(NULL),
68 fpOutputBlockCountArray(NULL),
69 fpTotalOutputSizeArray(NULL)
70 , fpInputOutputRatioArray(NULL)
71 , fpNormalizedInputOutputRatioArray(NULL)
72 , fpComponentCycleTimeArray(NULL)
73 , fpEventTypeArray(NULL)
74 , fpEventCountArray(NULL)
75 , fSizeEstimator(1000)
76 , fMode(kPublishObjects)
79 , fLastTime(time(NULL))
83 // see header file for class documentation
85 // refer to README to build package
87 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
90 AliHLTCompStatCollector::~AliHLTCompStatCollector()
92 // see header file for class documentation
96 void AliHLTCompStatCollector::GetInputDataTypes( vector<AliHLTComponentDataType>& list)
98 // see header file for class documentation
99 list.push_back(kAliHLTDataTypeComponentStatistics);
102 AliHLTComponentDataType AliHLTCompStatCollector::GetOutputDataType()
104 // see header file for class documentation
105 return kAliHLTMultipleDataType;
108 int AliHLTCompStatCollector::GetOutputDataTypes(AliHLTComponentDataTypeList& tgtList)
110 // see header file for class documentation
112 tgtList.push_back(kAliHLTDataTypeHistogram);
113 tgtList.push_back(kAliHLTDataTypeTTree);
114 return tgtList.size();
117 void AliHLTCompStatCollector::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
119 // see header file for class documentation
120 constBase=fSizeEstimator;
121 inputMultiplier=100.0;
124 int AliHLTCompStatCollector::DoInit( int argc, const char** argv )
126 // see header file for class documentation
130 for (int i=0; i<argc && iResult>=0; i++) {
132 if (argument.IsNull()) continue;
135 if (argument.CompareTo("-file")==0) {
136 if ((bMissingParam=(++i>=argc))) break;
141 } else if (argument.CompareTo("-modulo")==0) {
142 if ((bMissingParam=(++i>=argc))) break;
143 TString param=argv[i];
144 if (param.IsDigit()) {
145 fEventModulo=param.Atoi();
147 HLTError("expecting number as parameter for option %s", argument.Data());
152 } else if (argument.CompareTo("-period")==0) {
153 if ((bMissingParam=(++i>=argc))) break;
154 TString param=argv[i];
155 if (param.IsDigit()) {
156 fPeriod=param.Atoi();
158 HLTError("expecting number as parameter for option %s", argument.Data());
163 } else if (argument.CompareTo("-publish")==0) {
164 if ((bMissingParam=(++i>=argc))) break;
165 TString param=argv[i];
166 if (param.IsDigit()) {
167 if (param.Atoi()==1) fMode|=kPublishObjects;
168 else if (param.Atoi()==0) fMode&=~kPublishObjects;
170 HLTError("expecting 0 or 1 as parameter for option %s", argument.Data());
174 HLTError("expecting number as parameter for option %s", argument.Data());
179 } else if (argument.CompareTo("-arraysize")==0) {
180 if ((bMissingParam=(++i>=argc))) break;
181 TString param=argv[i];
182 if (param.IsDigit()) {
183 fArraySize=param.Atoi();
185 HLTError("expecting number as parameter for option %s", argument.Data());
190 HLTError("unknown argument %s", argument.Data());
195 HLTError("missing parameter for argument %s", argument.Data());
200 fpLevelArray=new UInt_t[fArraySize];
201 fpSpecArray=new UInt_t[fArraySize];
202 fpBlockNoArray=new UInt_t[fArraySize];
203 fpIdArray=new UInt_t[fArraySize];
204 fpTimeArray=new UInt_t[fArraySize];
205 fpCTimeArray=new UInt_t[fArraySize];
206 fpInputBlockCountArray=new UInt_t[fArraySize];
207 fpTotalInputSizeArray=new UInt_t[fArraySize];
208 fpNormalizedInputSizeArray=new UInt_t[fArraySize];
209 fpOutputBlockCountArray=new UInt_t[fArraySize];
210 fpTotalOutputSizeArray=new UInt_t[fArraySize];
211 fpInputOutputRatioArray=new UInt_t[fArraySize];
212 fpNormalizedInputOutputRatioArray=new UInt_t[fArraySize];
213 fpComponentCycleTimeArray=new UInt_t[fArraySize];
214 fpEventTypeArray=new UInt_t[fArraySize];
215 fpEventCountArray=new UInt_t[fArraySize];
217 fpStatTree=new TTree("CompStat", "HLT component statistics");
219 fpStatTree->SetDirectory(0);
220 fpStatTree->Branch("cycleTime", &fCycleTime, "cycleTime/F");
221 fpStatTree->Branch("nofSets", &fNofSets, "nofSets/I");
222 fpStatTree->Branch("Level", fpLevelArray, "Level[nofSets]/i");
223 fpStatTree->Branch("Specification", fpSpecArray, "Specification[nofSets]/i");
224 fpStatTree->Branch("BlockNo", fpBlockNoArray, "BlockNo[nofSets]/i");
225 fpStatTree->Branch("Id", fpIdArray, "Id[nofSets]/i");
226 fpStatTree->Branch("Time", fpTimeArray, "Time[nofSets]/i");
227 fpStatTree->Branch("CTime", fpCTimeArray, "CTime[nofSets]/i");
228 fpStatTree->Branch("InputBlockCount", fpInputBlockCountArray, "InputBlockCount[nofSets]/i");
229 fpStatTree->Branch("TotalInputSize", fpTotalInputSizeArray, "TotalInputSize[nofSets]/i");
230 fpStatTree->Branch("NormalizedInputSize", fpNormalizedInputSizeArray, "NormalizedInputSize[nofSets]/i");
231 fpStatTree->Branch("OutputBlockCount", fpOutputBlockCountArray, "OutputBlockCount[nofSets]/i");
232 fpStatTree->Branch("TotalOutputSize", fpTotalOutputSizeArray, "TotalOutputSize[nofSets]/i");
233 fpStatTree->Branch("InputOutputRatio", fpInputOutputRatioArray, "InputOutputRatio[nofSets]/i");
234 fpStatTree->Branch("NormalizedInputOutputRatio", fpNormalizedInputOutputRatioArray, "NormalizedInputOutputRatio[nofSets]/i");
235 fpStatTree->Branch("ComponentCycleTime",fpComponentCycleTimeArray, "ComponentCycleTime[nofSets]/i");
236 fpStatTree->Branch("EventType",fpEventTypeArray, "EventType[nofSets]/i");
237 fpStatTree->Branch("EventCount",fpEventCountArray, "EventCount[nofSets]/i");
241 if (!fFileName.empty()) {
242 fFile=new TFile(fFileName.c_str(), "RECREATE");
247 int AliHLTCompStatCollector::DoDeinit( )
249 // see header file for class documentation
260 int AliHLTCompStatCollector::DoEvent( const AliHLTComponentEventData& /*evtData*/, AliHLTComponentTriggerData& /*trigData*/)
262 // see header file for class documentation
265 AliHLTUInt32_t eventType=gkAliEventTypeUnknown;
266 IsDataEvent(&eventType);
268 ResetFillingVariables();
270 fCycleTime=fpTimer->RealTime()*1000000;
273 bool bEmbeddedTree=false;
274 bool bFolderCreated=false;
275 if ((bFolderCreated=(fpFolder==NULL))) {
276 fpFolder=new TFolder(HLTSTAT_FOLDER_NAME, HLTSTAT_FOLDER_DESC);
277 if (bEmbeddedTree) fpFolder->Add(fpStatTree);
279 if (!fpFolder) return -ENOMEM;
280 vector<TFolder*> newFolders;
282 for (const AliHLTComponentBlockData* pBlock=GetFirstInputBlock(kAliHLTDataTypeComponentTable);
283 pBlock && iResult>=0;
284 pBlock=GetNextInputBlock()) {
285 string chainId, compId, compArgs;
286 vector<AliHLTUInt32_t> parents;
287 iResult=ExtractComponentTableEntry((const AliHLTUInt8_t*)pBlock->fPtr, pBlock->fSize,
288 chainId, compId, compArgs,
291 HLTDebug("%s(%s) 0x%08x", chainId.c_str(), compId.c_str(), pBlock->fSpecification);
293 TFolder* pEntry=NULL;
294 if ((pObj=fpFolder->FindObjectAny(chainId.c_str()))!=NULL &&
295 (pEntry=dynamic_cast<TFolder*>(pObj))!=NULL ) {
298 HLTError("entry %s exists in folder, but is not a sub-folder", chainId.c_str());
299 } else if (chainId.size()>0) {
300 pEntry=new TFolder(chainId.c_str(), chainId.c_str());
303 TFolder* pProps=pEntry->AddFolder(HLTSTAT_ENTRY_PROPS_FOLDER_NAME, HLTSTAT_ENTRY_PROPS_FOLDER_DESC);
305 pProps->Add(new TObjString(compId.c_str()));
306 if (!compArgs.empty())
307 pProps->Add(new TObjString(compArgs.c_str()));
308 TNamed* pCRC=new TNamed(HLTSTAT_ENTRY_PROPS_IDOBJ_NAME, HLTSTAT_ENTRY_PROPS_IDOBJ_DESC);
310 pCRC->SetUniqueID(pBlock->fSpecification);
314 TFolder* pParents=pEntry->AddFolder(HLTSTAT_ENTRY_PARENT_FOLDER_NAME, HLTSTAT_ENTRY_PARENT_FOLDER_DESC);
316 for (vector<AliHLTUInt32_t>::iterator parent=parents.begin();
317 parent!=parents.end(); parent++) {
318 TString name; name.Form("0x%08x", *parent);
319 pParents->Add(new TObjString(name));
322 if (parents.size()==0) {
323 newFolders.push_back(pEntry);
325 vector<TFolder*>::iterator iter=newFolders.begin();
326 vector<AliHLTUInt32_t>::iterator parent=parents.begin();
327 while (iter!=newFolders.end() && parent!=parents.end()) {
328 TObject* idobj=(*iter)->FindObjectAny(HLTSTAT_ENTRY_PROPS_IDOBJ_NAME);
329 AliHLTUInt32_t crcid=0;
330 if (idobj) crcid=idobj->GetUniqueID();
331 HLTDebug("check: %s 0x%08x", (*iter)->GetName(), crcid);
332 if (idobj && crcid==*parent) break;
333 if ((++parent!=parents.end())) continue;
334 parent=parents.begin();
337 newFolders.insert(iter,pEntry);
341 HLTError("missing chain id for table entry 0x%08x (%p %d), skipping ...", pBlock->fSpecification, pBlock->fPtr, pBlock->fSize);
343 } else if (iResult!=0) {
344 HLTError("extraction of table entry 0x%08x (%p %d) failed with %d", pBlock->fSpecification, pBlock->fPtr, pBlock->fSize, iResult);
349 if (newFolders.size()>0) {
350 vector<TFolder*> revert;
351 vector<TFolder*>::iterator iter=newFolders.begin();
352 while (iter!=newFolders.end()) {
353 revert.insert(revert.begin(), *iter);
354 HLTDebug("%s", (*iter)->GetName());
358 newFolders.assign(revert.begin(), revert.end());
360 vector<TFolder*>::iterator publisher=newFolders.begin();
361 while (publisher!=newFolders.end()) {
363 HLTDebug("checking %s for parents", (*publisher)->GetName());
364 TFolder* propsFolder=dynamic_cast<TFolder*>((*publisher)->FindObject(HLTSTAT_ENTRY_PROPS_FOLDER_NAME));
367 if (propsFolder) idobj=propsFolder->FindObject(HLTSTAT_ENTRY_PROPS_IDOBJ_NAME);
369 AliHLTUInt32_t crcid=idobj->GetUniqueID();
370 TString idstr; idstr.Form("0x%08x", crcid);
372 for (vector<TFolder*>::iterator consumer=publisher+1;
373 consumer!=newFolders.end(); consumer++) {
374 HLTDebug(" checking %s", (*consumer)->GetName());
375 TFolder* parentFolder=dynamic_cast<TFolder*>((*consumer)->FindObject(HLTSTAT_ENTRY_PARENT_FOLDER_NAME));
376 assert(parentFolder);
378 TIter entries(parentFolder->GetListOfFolders());
379 while (TObject* entry=entries.Next())
382 HLTDebug(" searching %s in %s: %s", idstr.Data(), (*consumer)->GetName(), entry->GetName());
385 TObject* parent=parentFolder->FindObjectAny(idstr);
387 parentFolder->Add(*publisher);
388 parentFolder->Remove(parent);
394 if (bRemove) publisher=newFolders.erase(publisher);
398 for (publisher=newFolders.begin();
399 publisher!=newFolders.end(); publisher++) {
400 RemoveRecurrence(*publisher);
401 fpFolder->Add(*publisher);
406 for (const AliHLTComponentBlockData* pBlock=GetFirstInputBlock(kAliHLTDataTypeComponentStatistics);
407 pBlock && iResult>=0;
408 pBlock=GetNextInputBlock(), blockNo++) {
409 unsigned int current=fPosition;
410 iResult=FillVariablesSorted(pBlock->fPtr, pBlock->fSize, eventType);
411 for (; current<fPosition; current++) {
412 fpSpecArray[current]=pBlock->fSpecification;
413 fpBlockNoArray[current]=blockNo;
415 // indicate availability of component statistic block
419 int totalOutputSize=0;
420 if (iResult>0 && eventType) {
424 // init the timer for the next cycle
425 if (!fpTimer) fpTimer=new TStopwatch;
432 if (eventType==gkAliEventTypeEndOfRun ||
433 (iResult>=0 && CheckPeriod())) {
435 // publish objects to component output
436 if ((fMode&kPublishObjects)!=0) {
437 if (!bEmbeddedTree) {
438 iResult=PushBack(fpStatTree, kAliHLTDataTypeTTree|kAliHLTDataOriginOut);
439 totalOutputSize+=GetLastObjectSize();
441 iResult=PushBack(fpFolder, kAliHLTDataTypeTObject|kAliHLTDataOriginOut);
442 totalOutputSize+=GetLastObjectSize();
445 // save objects to file
446 if ((fMode&kSaveObjects)!=0 && fFile!=NULL) {
447 HLTDebug("saving objects to file %s", fFileName.c_str());
449 if (!bEmbeddedTree) {
450 fpStatTree->Write("", TObject::kOverwrite);
452 fpFolder->Write("", TObject::kOverwrite);
456 if (iResult==-ENOSPC) {
457 fSizeEstimator+=totalOutputSize;
460 if (iResult>0) iResult=0;
464 void AliHLTCompStatCollector::ResetFillingVariables()
466 // see header file for class documentation
470 memset(fpLevelArray, 0, sizeof(UInt_t)*fArraySize);
471 memset(fpSpecArray, 0, sizeof(UInt_t)*fArraySize);
472 memset(fpBlockNoArray, 0, sizeof(UInt_t)*fArraySize);
473 memset(fpIdArray, 0, sizeof(UInt_t)*fArraySize);
474 memset(fpTimeArray, 0, sizeof(UInt_t)*fArraySize);
475 memset(fpCTimeArray, 0, sizeof(UInt_t)*fArraySize);
476 memset(fpInputBlockCountArray, 0, sizeof(UInt_t)*fArraySize);
477 memset(fpTotalInputSizeArray, 0, sizeof(UInt_t)*fArraySize);
478 memset(fpNormalizedInputSizeArray, 0, sizeof(UInt_t)*fArraySize);
479 memset(fpOutputBlockCountArray, 0, sizeof(UInt_t)*fArraySize);
480 memset(fpTotalOutputSizeArray, 0, sizeof(UInt_t)*fArraySize);
481 memset(fpInputOutputRatioArray, 0, sizeof(UInt_t)*fArraySize);
482 memset(fpNormalizedInputOutputRatioArray, 0, sizeof(UInt_t)*fArraySize);
483 memset(fpComponentCycleTimeArray, 0, sizeof(UInt_t)*fArraySize);
484 memset(fpEventTypeArray, 0, sizeof(UInt_t)*fArraySize);
485 memset(fpEventCountArray, 0, sizeof(UInt_t)*fArraySize);
488 int AliHLTCompStatCollector::FillVariablesSorted(void* ptr, int size, AliHLTUInt32_t eventType)
490 // see header file for class documentation
492 if (size%sizeof(AliHLTComponentStatistics)) {
493 // older or invalid structure
494 HLTError("data block is not aligned to the size of the AliHLTComponentStatistics struct");
498 AliHLTComponentStatistics* pStat=reinterpret_cast<AliHLTComponentStatistics*>(ptr);
499 UInt_t nofStats=size/sizeof(AliHLTComponentStatistics);
500 vector<int> indexList;
502 for (i=0; i<nofStats; i++) {
503 vector<int>::iterator element=indexList.begin();
504 for (; element!=indexList.end(); element++) {
505 if (pStat[i].fLevel>pStat[*element].fLevel) {
509 indexList.insert(element, i);
513 for (vector<int>::iterator element=indexList.begin();
514 element!=indexList.end();
517 fpLevelArray[i]=pStat[*element].fLevel;
518 fpIdArray[i]=pStat[*element].fId;
519 fpTimeArray[i]=pStat[*element].fTime;
520 fpCTimeArray[i]=pStat[*element].fCTime;
521 fpInputBlockCountArray[i]=pStat[*element].fInputBlockCount;
522 fpTotalInputSizeArray[i]=pStat[*element].fTotalInputSize;
523 fpNormalizedInputSizeArray[i]=pStat[*element].fTotalInputSize;
524 if (pStat[*element].fInputBlockCount>0)
525 fpNormalizedInputSizeArray[i]/=pStat[*element].fInputBlockCount;
526 fpOutputBlockCountArray[i]=pStat[*element].fOutputBlockCount;
527 fpTotalOutputSizeArray[i]=pStat[*element].fTotalOutputSize;
528 if (pStat[*element].fTotalOutputSize>0)
529 fpInputOutputRatioArray[i]=pStat[*element].fTotalInputSize/pStat[*element].fTotalOutputSize;
530 if (pStat[*element].fInputBlockCount>0)
531 fpNormalizedInputOutputRatioArray[i]=fpInputOutputRatioArray[i]*pStat[*element].fOutputBlockCount/pStat[*element].fInputBlockCount;
532 fpComponentCycleTimeArray[i]=pStat[*element].fComponentCycleTime;
533 fpEventTypeArray[i]=eventType;
534 fpEventCountArray[i]=GetEventCount();
536 // TODO: dynamically grow arrays with placement new
541 HLTWarning("too little space in branch variables to fill %d statistics blocks, available %d at position %d", i, fArraySize, fPosition);
542 fPosition=fArraySize;
550 void AliHLTCompStatCollector::ClearAll()
552 // see header file for class documentation
553 if (fpTimer) delete fpTimer; fpTimer=NULL;
554 if (fpFolder) delete fpFolder; fpFolder=NULL;
555 if (fpStatTree) delete fpStatTree; fpStatTree=NULL;
556 if (fpLevelArray) delete fpLevelArray; fpLevelArray=NULL;
557 if (fpSpecArray) delete fpSpecArray; fpSpecArray=NULL;
558 if (fpBlockNoArray) delete fpBlockNoArray; fpBlockNoArray=NULL;
559 if (fpIdArray) delete fpIdArray; fpIdArray=NULL;
560 if (fpTimeArray) delete fpTimeArray; fpTimeArray=NULL;
561 if (fpCTimeArray) delete fpCTimeArray; fpCTimeArray=NULL;
562 if (fpInputBlockCountArray) delete fpInputBlockCountArray; fpInputBlockCountArray=NULL;
563 if (fpTotalInputSizeArray) delete fpTotalInputSizeArray; fpTotalInputSizeArray=NULL;
564 if (fpNormalizedInputSizeArray) delete fpNormalizedInputSizeArray; fpNormalizedInputSizeArray=NULL;
565 if (fpOutputBlockCountArray) delete fpOutputBlockCountArray; fpOutputBlockCountArray=NULL;
566 if (fpTotalOutputSizeArray) delete fpTotalOutputSizeArray; fpTotalOutputSizeArray=NULL;
567 if (fpInputOutputRatioArray) delete fpInputOutputRatioArray; fpInputOutputRatioArray=NULL;
568 if (fpNormalizedInputOutputRatioArray) delete fpNormalizedInputOutputRatioArray; fpNormalizedInputOutputRatioArray=NULL;
569 if (fpComponentCycleTimeArray) delete fpComponentCycleTimeArray; fpComponentCycleTimeArray=NULL;
570 if (fpEventTypeArray) delete fpEventTypeArray; fpEventTypeArray=NULL;
571 if (fpEventCountArray) delete fpEventCountArray; fpEventCountArray=NULL;
574 int AliHLTCompStatCollector::RemoveRecurrence(TFolder* pRoot) const
576 // see header file for class documentation
578 if (!pRoot) return -EINVAL;
579 TFolder* parentFolder=dynamic_cast<TFolder*>(pRoot->FindObject(HLTSTAT_ENTRY_PARENT_FOLDER_NAME));
580 assert(parentFolder);
581 vector<TFolder*> listRemove;
583 TIter entries(parentFolder->GetListOfFolders());
586 while ((obj=entries.Next())!=NULL && (entry=dynamic_cast<TFolder*>(obj))!=NULL) {
587 TString name=entry->GetName();
588 HLTDebug("checking %s for recurrence", name.Data());
589 TIter tokens(parentFolder->GetListOfFolders());
591 while ((obj=tokens.Next())!=NULL && (token=dynamic_cast<TFolder*>(obj))!=NULL) {
592 if (name.CompareTo(token->GetName())==0) continue;
593 if ((obj=token->FindObjectAny(name))!=NULL) {
594 listRemove.push_back(entry);
595 HLTDebug("found recurrence in %s", token->GetName());
598 HLTDebug("no recurrence found in %s", token->GetName());
601 RemoveRecurrence(entry);
603 for (vector<TFolder*>::iterator removeElement=listRemove.begin();
604 removeElement!=listRemove.end(); removeElement++) {
605 parentFolder->Remove(*removeElement);
612 bool AliHLTCompStatCollector::CheckPeriod(bool bUpdate)
614 // see header file for class documentation
616 if (fEventModulo>0) {
617 if ((result=((GetEventCount()+1)%fEventModulo)==0)) {
622 if ((result=((difftime(time(NULL), fLastTime)>(double)fPeriod))) &&
624 fLastTime=time(NULL);