added optional component statistics functionality
authorrichterm <richterm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Mon, 21 Jul 2008 12:12:05 +0000 (12:12 +0000)
committerrichterm <richterm@f7af4fe6-9843-0410-8265-dc069ae4e863>
Mon, 21 Jul 2008 12:12:05 +0000 (12:12 +0000)
HLT/BASE/AliHLTComponent.cxx
HLT/BASE/AliHLTComponent.h
HLT/BASE/AliHLTDataTypes.cxx
HLT/BASE/AliHLTDataTypes.h
HLT/BASE/AliHLTTask.cxx

index 6e8796a..0f12fd3 100644 (file)
@@ -73,7 +73,9 @@ AliHLTComponent::AliHLTComponent()
   fpRunDesc(NULL),
   fpDDLList(NULL),
   fCDBSetRunNoFunc(false),
-  fChainId()
+  fChainId(),
+  fpBenchmark(NULL),
+  fRequireSteeringBlocks(false)
 {
   // see header file for class documentation
   // or
@@ -89,6 +91,9 @@ AliHLTComponent::AliHLTComponent()
 AliHLTComponent::~AliHLTComponent()
 {
   // see header file for function documentation
+  if (fpBenchmark) delete fpBenchmark;
+  fpBenchmark=NULL;
+
   CleanupInputObjects();
   if (fpStopwatches!=NULL) delete fpStopwatches;
   fpStopwatches=NULL;
@@ -182,8 +187,33 @@ int AliHLTComponent::Init( AliHLTComponentEnvironment* comenv, void* environPara
   if (iResult>=0) {
     iResult=DoInit(iNofChildArgs, pArguments);
   }
-  if (iResult>=0) fEventCount=0;
+  if (iResult>=0) {
+    fEventCount=0;
+
+    // find out if the component wants to get the steering events
+    // explicitly
+    AliHLTComponentDataTypeList inputDt;
+    GetInputDataTypes(inputDt);
+    for (AliHLTComponentDataTypeList::iterator dt=inputDt.begin();
+        dt!=inputDt.end() && !fRequireSteeringBlocks;
+        dt++) {
+      fRequireSteeringBlocks|=MatchExactly(*dt,kAliHLTDataTypeSOR);
+      fRequireSteeringBlocks|=MatchExactly(*dt,kAliHLTDataTypeRunType);
+      fRequireSteeringBlocks|=MatchExactly(*dt,kAliHLTDataTypeEOR);
+      fRequireSteeringBlocks|=MatchExactly(*dt,kAliHLTDataTypeDDL);
+      fRequireSteeringBlocks|=MatchExactly(*dt,kAliHLTDataTypeComponentStatistics);
+    }
+  }
   if (pArguments) delete [] pArguments;
+
+#if defined(__DEBUG) || defined(HLT_COMPONENT_STATISTICS)
+  // benchmarking stopwatch for the component statistics
+  fpBenchmark=new TStopwatch;
+  if (fpBenchmark) {
+    fpBenchmark->Start();
+  }
+#endif
+
   return iResult;
 }
 
@@ -1183,6 +1213,16 @@ int AliHLTComponent::ProcessEvent( const AliHLTComponentEventData& evtData,
   fOutputBlocks.clear();
   outputBlockCnt=0;
   outputBlocks=NULL;
+  AliHLTComponentStatisticsList compStats;
+#if defined(__DEBUG) || defined(HLT_COMPONENT_STATISTICS)
+  AliHLTComponentStatistics outputStat;
+  memset(&outputStat, 0, sizeof(AliHLTComponentStatistics));
+  compStats.push_back(outputStat);
+  if (fpBenchmark) {
+    fpBenchmark->Reset();
+    fpBenchmark->Start();
+  }
+#endif
 
   // data processing is skipped if there are only steering events
   // in the block list. It is not skipped if there is no block list
@@ -1229,11 +1269,28 @@ int AliHLTComponent::ProcessEvent( const AliHLTComponentEventData& evtData,
        eventType=fpInputBlocks[i].fSpecification;
        if (fpInputBlocks[i].fSpecification==gkAliEventTypeConfiguration) bSkipDataProcessing|=skipModeForce;
        if (fpInputBlocks[i].fSpecification==gkAliEventTypeReadPreprocessor) bSkipDataProcessing|=skipModeForce;
+      } else if (fpInputBlocks[i].fDataType==kAliHLTDataTypeComponentStatistics) {
+       if (compStats.size()>0) {
+         AliHLTUInt8_t* pData=reinterpret_cast<AliHLTUInt8_t*>(fpInputBlocks[i].fPtr);
+         for (AliHLTUInt32_t offset=0;
+              offset+sizeof(AliHLTComponentStatistics)<=fpInputBlocks[i].fSize;
+              offset+=sizeof(AliHLTComponentStatistics)) {
+           AliHLTComponentStatistics* pStat=reinterpret_cast<AliHLTComponentStatistics*>(pData+offset);
+           if (pStat && compStats[0].fLevel<=pStat->fLevel) {
+             compStats[0].fLevel=pStat->fLevel+1;
+           }
+           compStats.push_back(*pStat);
+         }
+       }
       } else {
        // the processing function is called if there is at least one
        // non-steering data block. Steering blocks are not filtered out
        // for sake of performance 
        bSkipDataProcessing&=~skipModeDefault;
+       if (compStats.size()>0) {
+         compStats[0].fInputBlockCount++;
+         compStats[0].fTotalInputSize+=fpInputBlocks[i].fSize;
+       }
       }
     }
 
@@ -1303,7 +1360,11 @@ int AliHLTComponent::ProcessEvent( const AliHLTComponentEventData& evtData,
     // blocks in order to make data source components working.
     bSkipDataProcessing&=~skipModeDefault;
   }
-  
+
+  // data processing is not skipped if the component explicitly asks
+  // for the private blocks
+  if (fRequireSteeringBlocks) bSkipDataProcessing=0;
+
   AliHLTComponentBlockDataList blockData;
   if (iResult>=0 && !bSkipDataProcessing)
   { // dont delete, sets the scope for the stopwatch guard
@@ -1336,12 +1397,20 @@ int AliHLTComponent::ProcessEvent( const AliHLTComponentEventData& evtData,
          HLTError("low level and high interface must not be mixed; use PushBack methods to insert data blocks");
          iResult=-EFAULT;
        } else {
+         if (compStats.size()>0) {
+           int offset=AddComponentStatistics(fOutputBlocks, fpOutputBuffer, fOutputBufferSize, fOutputBufferFilled, compStats);
+           if (offset>0) fOutputBufferFilled+=offset;
+         }
          iResult=MakeOutputDataBlockList(fOutputBlocks, &outputBlockCnt, &outputBlocks);
          size=fOutputBufferFilled;
        }
       }
     } else {
       // Low Level interface
+      if (compStats.size()>0) {
+       int offset=AddComponentStatistics(blockData, fpOutputBuffer, fOutputBufferSize, size, compStats);
+       if (offset>0) size+=offset;
+      }
       iResult=MakeOutputDataBlockList(blockData, &outputBlockCnt, &outputBlocks);
     }
     if (iResult<0) {
@@ -1363,6 +1432,54 @@ int AliHLTComponent::ProcessEvent( const AliHLTComponentEventData& evtData,
   return iResult;
 }
 
+int  AliHLTComponent::AddComponentStatistics(AliHLTComponentBlockDataList& blocks, 
+                                            AliHLTUInt8_t* buffer,
+                                            AliHLTUInt32_t bufferSize,
+                                            AliHLTUInt32_t offset,
+                                            AliHLTComponentStatisticsList& stats) const
+{
+  // see header file for function documentation
+  int iResult=0;
+  if (stats.size()==0) return -ENOENT;
+  stats[0].fTotalOutputSize=offset;
+  stats[0].fOutputBlockCount=blocks.size();
+  if (fpBenchmark) {
+    stats[0].fTime=(AliHLTUInt32_t)(fpBenchmark->RealTime()*1000000);
+    stats[0].fCTime=(AliHLTUInt32_t)(fpBenchmark->CpuTime()*1000000);
+  }
+  if (offset+stats.size()*sizeof(AliHLTComponentStatistics)<=bufferSize) {
+    AliHLTComponentBlockData bd;
+    FillBlockData( bd );
+    bd.fOffset        = offset;
+    bd.fSize          = stats.size()*sizeof(AliHLTComponentStatistics);
+    bd.fDataType      = kAliHLTDataTypeComponentStatistics;
+    bd.fSpecification = kAliHLTVoidDataSpec;
+    unsigned int master=0;
+    for (unsigned int i=1; i<blocks.size(); i++) {
+      if (blocks[i].fSize>blocks[master].fSize && 
+         !MatchExactly(blocks[i].fDataType, kAliHLTVoidDataType|kAliHLTDataOriginPrivate))
+       master=i;
+    }
+    if (blocks.size()>0 && !MatchExactly(blocks[master].fDataType, kAliHLTVoidDataType|kAliHLTDataOriginPrivate)) {
+      // take the data origin of the biggest block as specification
+      // this is similar to the treatment in the HOMER interface. For traditional
+      // reasons, the bytes are swapped there on a little endian architecture, so
+      // we do it as well.
+      memcpy(&bd.fSpecification, &blocks[master].fDataType.fOrigin, sizeof(bd.fSpecification));
+#ifdef R__BYTESWAP // set on little endian architectures
+      bd.fSpecification=((bd.fSpecification & 0xFFULL) << 24) | 
+       ((bd.fSpecification & 0xFF00ULL) << 8) | 
+       ((bd.fSpecification & 0xFF0000ULL) >> 8) | 
+       ((bd.fSpecification & 0xFF000000ULL) >> 24);
+#endif
+    }
+    memcpy(buffer+offset, &(stats[0]), bd.fSize);
+    blocks.push_back(bd);
+    iResult=bd.fSize;
+  }
+  return iResult;
+}
+
 AliHLTComponent::AliHLTStopwatchGuard::AliHLTStopwatchGuard()
   :
   fpStopwatch(NULL),
index 98a574b..ae7f0ec 100644 (file)
@@ -88,6 +88,8 @@ class AliHLTMemoryFile;
 typedef vector<AliHLTComponentDataType>   AliHLTComponentDataTypeList;
 /** list of component block data structures */
 typedef vector<AliHLTComponentBlockData>  AliHLTComponentBlockDataList;
+/** list of component statistics struct */
+typedef vector<AliHLTComponentStatistics> AliHLTComponentStatisticsList;
 /** list of component pointers */
 typedef vector<AliHLTComponent*>          AliHLTComponentPList;
 /** list of memory file pointers */
@@ -1257,6 +1259,15 @@ class AliHLTComponent : public AliHLTLogging {
                        AliHLTUInt32_t spec,
                        void* pHeader=NULL, int iHeaderSize=0);
 
+  /**
+   * Add a component statistics block to the output.
+   */
+  int AddComponentStatistics(AliHLTComponentBlockDataList& blocks, 
+                            AliHLTUInt8_t* buffer,
+                            AliHLTUInt32_t bufferSize,
+                            AliHLTUInt32_t offset,
+                            AliHLTComponentStatisticsList& stats) const;
+
   /** The global component handler instance */
   static AliHLTComponentHandler* fgpComponentHandler;              //! transient
 
@@ -1320,6 +1331,12 @@ class AliHLTComponent : public AliHLTLogging {
   /** id of the component in the analysis chain */
   string fChainId;                                                 //! transient
 
-  ClassDef(AliHLTComponent, 6)
+  /** optional benchmarking for the component statistics */
+  TStopwatch* fpBenchmark;                                         //! transient
+
+  /** component requires steering data blocks */
+  bool fRequireSteeringBlocks;                                     //! transient
+
+  ClassDef(AliHLTComponent, 7)
 };
 #endif
index 6ed8cff..a8a6c10 100644 (file)
@@ -161,6 +161,20 @@ const AliHLTComponentDataType kAliHLTDataTypeRunSummary = (AliHLTComponentDataTy
   kAliHLTDataOriginAny
 }|kAliHLTDataOriginOut;
 
+/** Component statistics */
+const AliHLTComponentDataType kAliHLTDataTypeComponentStatistics = (AliHLTComponentDataType) {
+  sizeof(AliHLTComponentDataType),
+  kAliHLTComponentStatisticsDataTypeID,
+  kAliHLTDataOriginAny
+}|kAliHLTDataOriginPrivate;
+
+/** Component table */
+const AliHLTComponentDataType kAliHLTDataTypeComponentTable = (AliHLTComponentDataType) {
+  sizeof(AliHLTComponentDataType),
+  kAliHLTComponentTableDataTypeID,
+  kAliHLTDataOriginAny
+}|kAliHLTDataOriginPrivate;
+
 /** general ROOT TObject */
 const AliHLTComponentDataType kAliHLTDataTypeTObject = (AliHLTComponentDataType) {
   sizeof(AliHLTComponentDataType),
index b706a5d..227d3bd 100644 (file)
  *           kAliHLTAllDataTypes and kAliHLTDataOriginSample added
  *           kAliHLTDataOriginEMCAL added
  *           kAliHLTDataTypeRunType added
+ *   7       kAliHLTDataTypeComponentStatistics, kAliHLTDataTypeComponentTable,
+ *           and AliHLTComponentStatistics have been added for optional
+ *           component block statistics
  */
-#define ALIHLT_DATA_TYPES_VERSION 6
+#define ALIHLT_DATA_TYPES_VERSION 7
 
 //////////////////////////////////////////////////////////////////////////
 //
@@ -253,6 +256,21 @@ const int kAliHLTComponentDataTypefIDsize=8;
  */
 # define kAliHLTRunSummaryDataTypeID          {'R','U','N','S','U','M','M','A'}
 
+/** Block Statistics
+ * - small block statistics info added to the data stream by
+ *   the component base class
+ * - origin kAliHLTDataOriginPrivate
+ * @ingroup alihlt_component_datatypes
+ */
+# define kAliHLTComponentStatisticsDataTypeID {'C','O','M','P','S','T','A','T'}
+
+/** Component table
+ * - list of components in the chain to be percolated through the chain
+ * - each component adds it's chain id string and a generated 32bit id
+ * @ingroup alihlt_component_datatypes
+ */
+# define kAliHLTComponentTableDataTypeID      {'C','O','M','P','T','A','B','L'}
+
 /** general ROOT TObject
  * - a general TObject exported from the HLT analysis
  * - varying origin
@@ -470,6 +488,52 @@ extern "C" {
     AliHLTUInt32_t fRunType;
   };
 
+  /**
+   * @struct AliHLTComponentStatistics
+   * Small block size summary added by the AliHLTComponent base class
+   * if component statistics are enabled (--enable-compstat).
+   *
+   * fLevel is retrieved from incoming block statistics and incremented. 
+   * Incoming block statistics are appended to the newly added one if
+   * --enable-compstat=full has been chosen.
+   */
+  struct AliHLTComponentStatistics
+  {
+    AliHLTUInt32_t fStructSize;
+    AliHLTUInt32_t fLevel;
+    AliHLTUInt32_t fId;
+    AliHLTUInt32_t fTime;
+    AliHLTUInt32_t fCTime;
+    AliHLTUInt32_t fInputBlockCount;
+    AliHLTUInt32_t fTotalInputSize;
+    AliHLTUInt32_t fOutputBlockCount;
+    AliHLTUInt32_t fTotalOutputSize;
+  };
+
+  /**
+   * @struct AliHLTComponentTableEntry
+   * Structure to be send on SOR event through the chain. Each component
+   * adds its chain id and component arguments to the list.
+   * The 'length' of the structure is variable and depends on the length
+   * of the strings in the buffer at the end.
+   */
+  struct AliHLTComponentTableEntry
+  {
+    AliHLTUInt32_t fStructSize;
+    /** the 32bit Id is generated by a CRC algorithm from the
+        chain Id of the component. This is not a 100% unique id
+        but with a high probability */
+    AliHLTUInt32_t fId;
+    /** size of the chain id string in the appended buffer */
+    AliHLTUInt8_t  fSizeChainId;
+    /** size of the comp argument string in the appended buffer */
+    AliHLTUInt8_t  fSizeCompArgs;
+    /** some reserved size */
+    AliHLTUInt8_t  fSizeReserved;
+    /** the strings: chain id, component args, reserved */
+    AliHLTUInt8_t  fBuffer[1];
+  };
+
   //////////////////////////////////////////////////////////////////////////
   //
   // Trigger meta information
@@ -718,6 +782,18 @@ extern "C" {
    */
   extern const AliHLTComponentDataType kAliHLTDataTypeRunSummary;
 
+  /** Component block statistics
+   * @ingroup alihlt_component_datatypes
+   */
+  extern const AliHLTComponentDataType kAliHLTDataTypeComponentStatistics;
+
+  /** Component table
+   * To be sent on SOR event, each component adds it's chain id string
+   * and a generated 32bit identifier to the table
+   * @ingroup alihlt_component_datatypes
+   */
+  extern const AliHLTComponentDataType kAliHLTDataTypeComponentTable;
+
   //////////////////////////////////////////////////////////////////////////
   //
   // Data Types for Monitoring objects
index a17e687..b4946eb 100644 (file)
@@ -540,7 +540,7 @@ int AliHLTTask::ProcessTask(Int_t eventNo)
       size=iOutputDataSize;
       AliHLTUInt32_t outputBlockCnt=0;
       AliHLTComponentBlockData* outputBlocks=NULL;
-      AliHLTComponentEventDoneData* edd;
+      AliHLTComponentEventDoneData* edd=NULL;
       if (pTgtBuffer!=NULL || iOutputDataSize==0) {
        iResult=pComponent->ProcessEvent(evtData, &fBlockDataArray[0], trigData, pTgtBuffer, size, outputBlockCnt, outputBlocks, edd);
        HLTDebug("task %s: component %s ProcessEvent finnished (%d): size=%d blocks=%d", GetName(), pComponent->GetComponentID(), iResult, size, outputBlockCnt);