#include "TString.h"
#include "TTree.h"
#include "TH1.h"
+#include "TStopwatch.h"
/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTTTreeProcessor)
fTree(0),
fMaxEntries(kMaxEntries),
fPublishInterval(kInterval),
- fLastTime(0)
+ fLastTime(0),
+ fpEventTimer(NULL),
+ fpCycleTimer(NULL),
+ fMaxEventTime(0),
+ fNofEventsForce(0),
+ fForcedEventsCount(0),
+ fSkippedEventsCount(0),
+ fNewEventsCount(0)
{
// see header file for class documentation
// or
// visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
}
+const AliHLTUInt32_t AliHLTTTreeProcessor::fgkTimeScale=1000000; // ticks per second
+
AliHLTTTreeProcessor::~AliHLTTTreeProcessor()
{
// see header file for class documentation
return -EINVAL;
}
+ if (iResult>=0 && fMaxEventTime>0) {
+ fpEventTimer=new TStopwatch;
+ if (fpEventTimer) {
+ fpEventTimer->Reset();
+ }
+ fpCycleTimer=new TStopwatch;
+ if (fpCycleTimer) {
+ fpCycleTimer->Reset();
+ }
+ }
+ fSkippedEventsCount=0;
+
return iResult;
}
delete fTree;
fTree = 0;
fDefinitions.clear();
+
+ if (fpEventTimer) delete fpEventTimer;
+ fpEventTimer=NULL;
+ if (fpCycleTimer) delete fpCycleTimer;
+ fpCycleTimer=NULL;
+
return 0;
}
return -EINVAL;//-ENULLTREE? :)
}
+ AliHLTUInt32_t averageEventTime=0;
+ AliHLTUInt32_t averageCycleTime=0;
+
+ int fillingtime=0;
+ int publishtime=0;
+ bool bDoFilling=true;
+ bool bDoPublishing=false;
+ const int cycleResetInterval=1000;
+ if (fpEventTimer && fpCycleTimer) {
+ averageEventTime=(fpEventTimer->RealTime()*fgkTimeScale)/(GetEventCount()+1);
+ fillingtime=fpEventTimer->RealTime()*fgkTimeScale;
+ publishtime=fillingtime;
+ fpEventTimer->Start(kFALSE);
+ fpCycleTimer->Stop();
+ averageCycleTime=(fpCycleTimer->RealTime()*fgkTimeScale)/((GetEventCount()%cycleResetInterval)+1);
+ // adapt processing to 3/4 of the max time
+ bDoFilling=4*averageEventTime<3*fMaxEventTime || averageEventTime<averageCycleTime;
+ if (fNofEventsForce>0 && fForcedEventsCount<fNofEventsForce) {
+ fForcedEventsCount++;
+ bDoFilling=true;
+ }
+ }
+
// process input data blocks and fill the tree
int iResult = 0;
if (eventType!=gkAliEventTypeEndOfRun) {
- iResult=FillTree(fTree, evtData, trigData);
+ if (bDoFilling) {iResult=FillTree(fTree, evtData, trigData); fNewEventsCount++;}
+ else fSkippedEventsCount++;
+ }
+ if (fpEventTimer) {
+ fpEventTimer->Stop();
+ fillingtime=fpEventTimer->RealTime()*fgkTimeScale-fillingtime;
+ fpEventTimer->Start(kFALSE);
}
if (iResult < 0)
const TDatime time;
- if (fLastTime - time.Get() > fPublishInterval ||
+ if (( time.Get() - fLastTime > fPublishInterval && fNewEventsCount>0) ||
eventType==gkAliEventTypeEndOfRun) {
+ bDoPublishing=true;
for (list_const_iterator i = fDefinitions.begin(); i != fDefinitions.end(); ++i) {
if (TH1* h = CreateHistogram(*i)) {
//I do not care about errors here - since I'm not able
PushBack(h, GetOriginDataType(), GetDataSpec());
}
}
+ unsigned eventcount=GetEventCount()+1;
+ HLTBenchmark("publishing %d histograms, %d entries in tree, %d new events since last publishing, accumulated %d of %d events (%.1f%%)", fDefinitions.size(), fTree->GetEntriesFast(), fNewEventsCount, eventcount-fSkippedEventsCount, eventcount, eventcount>0?(100*float(eventcount-fSkippedEventsCount)/eventcount):0);
+ fNewEventsCount=0;
fLastTime = time.Get();
}
+ if (fpEventTimer) {
+ fpEventTimer->Stop();
+ publishtime=fpEventTimer->RealTime()*fgkTimeScale-publishtime;
+ if (publishtime>fillingtime) publishtime-=fillingtime;
+ else publishtime=0;
+
+ averageEventTime=(fpEventTimer->RealTime()*fgkTimeScale)/(GetEventCount()+1);
+
+ // info output once every 5 seconds
+ static UInt_t lastTime=0;
+ if (time.Get()-lastTime>5 ||
+ eventType==gkAliEventTypeEndOfRun ||
+ bDoPublishing) {
+ lastTime=time.Get();
+ unsigned eventcount=GetEventCount()+1;
+ HLTBenchmark("filling time %d us, publishing time %d, average total processing time %d us, cycle time %d us, accumulated %d of %d events (%.1f%%)", fillingtime, publishtime, averageEventTime, averageCycleTime, eventcount-fSkippedEventsCount, eventcount, eventcount>0?(100*float(eventcount-fSkippedEventsCount)/eventcount):0);
+ }
+ }
+ if (fpCycleTimer) {
+ bool bReset=(GetEventCount()%cycleResetInterval)==0;
+ fpCycleTimer->Start(bReset);
+ }
+
return iResult;
}
fPublishInterval = interval;
+ i += 2;
+ } else if (argument.CompareTo("-maxeventtime") == 0) { // max average processing time in us
+ if (i + 1 == argc) {
+ HLTError("Numeric value for '-maxeventtime' is expected");
+ return -EPROTO;
+ }
+
+ const Int_t time = TString(argv[i + 1]).Atoi();
+ if (time <= 0) {
+ HLTError("Bad value for '-maxeventtime' argument: %d", time);
+ return -EPROTO;
+ }
+
+ fMaxEventTime = time;
+
+ i += 2;
+ } else if (argument.CompareTo("-forced-events") == 0) { // number of forced events
+ if (i + 1 == argc) {
+ HLTError("Numeric value for '-forced-events' is expected");
+ return -EPROTO;
+ }
+
+ const Int_t count = TString(argv[i + 1]).Atoi();
+ if (count <= 0) {
+ HLTError("Bad value for '-forced-events' argument: %d", count);
+ return -EPROTO;
+ }
+
+ fNofEventsForce = count;
+ fForcedEventsCount=0;
+
i += 2;
} else if (argument.CompareTo("-histogram") == 0) { //3. Histogramm definition.
const int nParsed = ParseHistogramDefinition(argc, argv, i, def);