#include <memory>
#include "AliHLTTTreeProcessor.h"
+#include "AliHLTErrorGuard.h"
#include "TDirectory.h"
#include "TDatime.h"
#include "TString.h"
#include "TTree.h"
#include "TH1.h"
#include "TStopwatch.h"
+#include "TUUID.h"
+#include "TSystem.h"
+#include "TRandom3.h"
/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTTTreeProcessor)
fLastTime(0),
fpEventTimer(NULL),
fpCycleTimer(NULL),
+ fMaxMemory(700000),
fMaxEventTime(0),
fNofEventsForce(0),
fForcedEventsCount(0),
- fSkippedEventsCount(0)
+ fSkippedEventsCount(0),
+ fNewEventsCount(0),
+ fUniqueId(0),
+ fIgnoreCycleTime(10),
+ fCycleTimeFactor(1.0)
{
// see header file for class documentation
// or
// ask child to create the tree.
int iResult = 0;
+ // component configuration
+ //Stage 1: default initialization.
+ //"Default" (for derived component) histograms.
+ FillHistogramDefinitions();
+ //Default values.
+ fMaxEntries = kMaxEntries;
+ fPublishInterval = kInterval;
+ fLastTime = 0;
+ //Stage 2: OCDB.
+ TString cdbPath("HLT/ConfigHLT/");
+ cdbPath += GetComponentID();
+ //
+ iResult = ConfigureFromCDBTObjString(cdbPath);
+ //
+ if (iResult < 0)
+ return iResult;
+ //Stage 3: command line arguments.
+ if (argc && (iResult = ConfigureFromArgumentString(argc, argv)) < 0)
+ return iResult;
+
+ // calculating a unique id from the hostname and process id
+ // used for identifying output of multiple components
+ TUUID guid = GenerateGUID();
+ union
+ {
+ UChar_t buf[16];
+ UInt_t bufAsInt[4];
+ };
+ guid.GetUUID(buf);
+ fUniqueId = bufAsInt[0];
+
if (!fTree) {
- std::auto_ptr<TTree> ptr(CreateTree(argc, argv));
+ // originally foreseen to pass the arguments to the function, however
+ // this is not appropriate. Argument scan via overloaded function
+ // ScanConfigurationArgument
+ std::auto_ptr<TTree> ptr(CreateTree(0, NULL));
if (ptr.get()) {
- //Stage 1: default initialization.
ptr->SetDirectory(0);
- //"Default" (for derived component) histograms.
- FillHistogramDefinitions();
- //Default values.
- fMaxEntries = kMaxEntries;
- fPublishInterval = kInterval;
- fLastTime = 0;
- //Stage 2: OCDB.
- TString cdbPath("HLT/ConfigHLT/");
- cdbPath += GetComponentID();
- //
- iResult = ConfigureFromCDBTObjString(cdbPath);
- //
- if (iResult < 0)
- return iResult;
- //Stage 3: command line arguments.
- if (argc && (iResult = ConfigureFromArgumentString(argc, argv)) < 0)
- return iResult;
-
ptr->SetCircular(fMaxEntries);
fTree = ptr.release();
} else //No way to process error correctly - error is unknown here.
AliHLTUInt32_t averageEventTime=0;
AliHLTUInt32_t averageCycleTime=0;
- AliHLTUInt32_t proctime=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);
- proctime=fpEventTimer->RealTime()*fgkTimeScale;
+ averageEventTime=AliHLTUInt32_t(fpEventTimer->RealTime()*fgkTimeScale)/(GetEventCount()+1);
+ fillingtime=int(fpEventTimer->RealTime()*fgkTimeScale);
+ publishtime=fillingtime;
fpEventTimer->Start(kFALSE);
fpCycleTimer->Stop();
- averageCycleTime=(fpCycleTimer->RealTime()*fgkTimeScale)/(GetEventCount()+1);
+ averageCycleTime=AliHLTUInt32_t(fpCycleTimer->RealTime()*fgkTimeScale)/((GetEventCount()%cycleResetInterval)+1);
// adapt processing to 3/4 of the max time
- bDoFilling=4*averageEventTime<3*fMaxEventTime || averageEventTime<averageCycleTime;
+ bDoFilling=4*averageEventTime<3*fMaxEventTime ||
+ (averageEventTime<fCycleTimeFactor*averageCycleTime && fpCycleTimer->RealTime()>fIgnoreCycleTime);
if (fNofEventsForce>0 && fForcedEventsCount<fNofEventsForce) {
fForcedEventsCount++;
bDoFilling=true;
}
}
+ // FIXME: there is still an unclear increase in memory consumption, even if the number of entries
+ // in the tree is restricted. Valgrind studies did not show an obvious memory leak. This is likely
+ // to be caused by something deep in the Root TTree functionality and needs to be studied in detail.
+ ProcInfo_t ProcInfo;
+ gSystem->GetProcInfo(&ProcInfo);
+ if (ProcInfo.fMemResident>fMaxMemory) bDoFilling=false;
+
// process input data blocks and fill the tree
int iResult = 0;
if (eventType!=gkAliEventTypeEndOfRun) {
- if (bDoFilling) iResult=FillTree(fTree, evtData, trigData);
+ if (bDoFilling) {iResult=FillTree(fTree, evtData, trigData); fNewEventsCount++;}
else fSkippedEventsCount++;
}
+ if (fpEventTimer) {
+ fpEventTimer->Stop();
+ fillingtime=int(fpEventTimer->RealTime()*fgkTimeScale)-fillingtime;
+ if (fillingtime<0) fillingtime=0;
+ fpEventTimer->Start(kFALSE);
+ }
- if (iResult < 0)
+ if (iResult < 0) {
+ ALIHLTERRORGUARD(5, "FillTree failed with %d, first event %d", iResult, GetEventCount());
return iResult;
+ }
const TDatime time;
- if ( time.Get() - fLastTime > fPublishInterval ||
+ if (( time.Get() - fLastTime > fPublishInterval && fNewEventsCount>0) ||
eventType==gkAliEventTypeEndOfRun) {
+ if ((bDoPublishing=fLastTime>0)) { // publish earliest after the first interval but set the timer
+
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
// TODO: in case of -ENOSPC et the size of the last object by calling
// GetLastObjectSize() and accumulate the necessary output buffer size
PushBack(h, GetOriginDataType(), GetDataSpec());
+ delete h;
}
}
+ 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;
+ HLTBenchmark("current memory usage %d %d", ProcInfo.fMemResident, ProcInfo.fMemVirtual);
+ }
- fLastTime = time.Get();
+ fLastTime=time.Get();
+ if (fLastTime==0) {
+ // choose a random offset at beginning to equalize traffic for multiple instances
+ // of the component
+ gRandom->SetSeed(fUniqueId);
+ fLastTime-=gRandom->Integer(fPublishInterval);
+ }
}
if (fpEventTimer) {
fpEventTimer->Stop();
- proctime=fpEventTimer->RealTime()*fgkTimeScale-proctime;
- averageEventTime=(fpEventTimer->RealTime()*fgkTimeScale)/(GetEventCount()+1);
+ publishtime=int(fpEventTimer->RealTime()*fgkTimeScale)-publishtime;
+ if (publishtime>fillingtime) publishtime-=fillingtime;
+ else publishtime=0;
+
+ averageEventTime=AliHLTUInt32_t(fpEventTimer->RealTime()*fgkTimeScale)/(GetEventCount()+1);
// info output once every 5 seconds
static UInt_t lastTime=0;
if (time.Get()-lastTime>5 ||
- eventType==gkAliEventTypeEndOfRun) {
+ eventType==gkAliEventTypeEndOfRun ||
+ bDoPublishing) {
lastTime=time.Get();
- unsigned eventcount=GetEventCount();
- HLTBenchmark("event time %d us, average time %d us, cycle time %d us, accumulated %d of %d events (%.1f%%)", proctime, averageEventTime, averageCycleTime, eventcount-fSkippedEventsCount, eventcount, eventcount>0?(100*float(eventcount-fSkippedEventsCount)/eventcount):0);
+ 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) {
- fpCycleTimer->Start(kFALSE);
+ bool bReset=(GetEventCount()%cycleResetInterval)==0;
+ fpCycleTimer->Start(bReset);
}
return iResult;
// possible arguments:
// -maxentries number
// -interval number
- // -histogram name -size number -expression expression [-cut expression ][-opt option]
+ // -histogram name -size number -expression expression [-title expression ] -cut expression ][-opt option]
// As soon as "-histogram" found, -size and -expression and -outtype are required,
// cut and option can be omitted.
if (argc <= 0)
AliHLTHistogramDefinition def;
int i = 0;
- int maxEntries = 0;
+ int maxEntries = fMaxEntries;
while (i < argc) {
const TString argument(argv[i]);
}
const Int_t interval = TString(argv[i + 1]).Atoi();
- if (interval <= 0) {
+ if (interval < 0) {
HLTError("Bad value for '-interval' argument: %d", interval);
return -EPROTO;
}
}
const Int_t time = TString(argv[i + 1]).Atoi();
- if (time <= 0) {
+ if (time < 0) {
HLTError("Bad value for '-maxeventtime' argument: %d", time);
return -EPROTO;
}
}
const Int_t count = TString(argv[i + 1]).Atoi();
- if (count <= 0) {
+ if (count < 0) {
HLTError("Bad value for '-forced-events' argument: %d", count);
return -EPROTO;
}
fNofEventsForce = count;
fForcedEventsCount=0;
+ i += 2;
+ } else if (argument.CompareTo("-ignore-cycletime") == 0) { // ignore cycle time for n sec
+ if (i + 1 == argc) {
+ HLTError("Numeric value for '-ignore-cycletime' is expected");
+ return -EPROTO;
+ }
+
+ const Int_t time = TString(argv[i + 1]).Atoi();
+ if (time < 0) {
+ HLTError("Bad value for '-ignore-cycletime' argument: %d", time);
+ return -EPROTO;
+ }
+
+ fIgnoreCycleTime = time;
+ i += 2;
+ } else if (argument.CompareTo("-maxmemory") == 0) { // maximum of memory in kByte to be used by the component
+ if (i + 1 == argc) {
+ HLTError("Numeric value for '-maxmemory' is expected");
+ return -EPROTO;
+ }
+
+ const Int_t mem = TString(argv[i + 1]).Atoi();
+ if (mem < 0) {
+ HLTError("Bad value for '-maxmemory' argument: %d", time);
+ return -EPROTO;
+ }
+
+ fMaxMemory = mem;
+ i += 2;
+ } else if (argument.CompareTo("-cycletime-factor") == 0) { // weight factor for cycle time
+ if (i + 1 == argc) {
+ HLTError("Numeric value for '-cycletime-factor' is expected");
+ return -EPROTO;
+ }
+
+ const Float_t factor = TString(argv[i + 1]).Atof();
+ if (factor < 0) {
+ HLTError("Bad value for '-cycletime-factor' argument: %f", factor);
+ return -EPROTO;
+ }
+
+ fCycleTimeFactor = factor;
i += 2;
} else if (argument.CompareTo("-histogram") == 0) { //3. Histogramm definition.
const int nParsed = ParseHistogramDefinition(argc, argv, i, def);
hist->SetOption(d.GetDrawOption().Data());
}
+ //Reformatting the histogram name
+ TString str2=d.GetCut().Data();
+ str2.ReplaceAll("Track_", "");
+ str2.ReplaceAll("&&", " ");
+ str2 = histName+" "+str2;
+ hist->SetTitle(str2);
+
+ if(d.GetTitle().Length()){
+
+ //removing underscore
+ size_t found;
+ string str=d.GetTitle().Data();
+ found=str.find_first_of("_");
+ if(!(d.GetExpression().CompareTo("Track_pt"))){
+ found=str.find_first_of("_",found+1);
+ }
+ str[found]=' ';
+ char axis[100];
+ sprintf(axis,"%s",str.c_str());
+
+ hist->SetXTitle(axis);
+ hist->GetXaxis()->CenterTitle();
+ }
return hist;
}
int AliHLTTTreeProcessor::ParseHistogramDefinition(int argc, const char** argv, int pos, AliHLTHistogramDefinition& dst)const
{
//Histogram-definition:
- // -histogram name -size number -expression expression [-cut expression][-opt option]
+ // -histogram name -size number -expression expression [-title expression][-cut expression][-opt option]
//at pos we have '-histogram', at pos + 1 must be the name.
if (pos + 1 == argc) {
pos += 2;
int processed = 6;
+ dst.SetTitle("");
dst.SetCut("");
dst.SetDrawOption("");
- //remaining options can be the cut and Draw option.
- //cut must be first.
+ //remaining options can be the title, cut and Draw option.
+ //title must be first
+ if (pos + 1 >= argc){
+ return processed;
+ }
+ if (TString(argv[pos]).CompareTo("-title") == 0) {
+ dst.SetTitle(argv[pos + 1]);
+ pos += 2;
+ processed += 2;
+ }
+
+ //cut must be second.
if (pos + 1 >= argc)
return processed;