Make the Scan method public
[u/mrichter/AliRoot.git] / MUON / MUONTimeRawStreamTrigger.C
1 /**************************************************************************
2  * This file is property of and copyright by the ALICE HLT Project        *
3  * All rights reserved.                                                   *
4  *                                                                        *
5  * Primary Authors:                                                       *
6  *   Artur Szostak <artursz@iafrica.com>                                  *
7  *                                                                        *
8  * Permission to use, copy, modify and distribute this software and its   *
9  * documentation strictly for non-commercial purposes is hereby granted   *
10  * without fee, provided that the above copyright notice appears in all   *
11  * copies and that both the copyright notice and this permission notice   *
12  * appear in the supporting documentation. The authors make no claims     *
13  * about the suitability of this software for any purpose. It is          *
14  * provided "as is" without express or implied warranty.                  *
15  **************************************************************************/
16
17 /// \ingroup macros
18 /// \file MUONTimeRawStreamTrigger.C
19 /// \brief Macro for checking the timing (speed) performace of the two different trigger decoders.
20 ///
21 /// \author Artur Szostak <artursz@iafrica.com>
22 ///
23 /// This macro is used to check the timing (speed) performance of the existing
24 /// offline decoder for the trigger DDLs and also for the new high performance
25 /// decoder. It can be invoked as follows:
26 /// 
27 ///  $ aliroot
28 /// .L $ALICE_ROOT/MUON/MUONTimeRawStreamTrigger.C+
29 ///  MUONTimeRawStreamTrigger(filename, maxEvent);
30 ///
31 /// where \em filename is the name of a file containing the raw data, or alternatively
32 /// the directory containing rawX (X being an integer) paths with the raw DDL
33 /// data. The \em maxEvent value is the maximum event to process (default set to
34 /// 1000). Thus the macro will time the algorithm for all events in the range
35 /// [0 .. maxEvent-1].
36 ///
37
38 #if !defined(__CINT__) || defined(__MAKECINT__)
39
40 #include "AliCodeTimer.h"
41
42 // MUON includes
43 #include "AliMUONRawStreamTrigger.h"
44 #include "AliMUONRawStreamTriggerHP.h"
45 #include "AliMUONDarcHeader.h"
46 #include "AliMUONRegHeader.h"
47 #include "AliMUONLocalStruct.h"
48 #include "AliMUONDDLTrigger.h"
49
50 // RAW includes
51 #include "AliRawReader.h"
52 #include "AliRawReaderMemory.h"
53 #include "AliRawDataHeader.h"
54
55 #include "TStopwatch.h"
56 #include "TMath.h"
57 #include "Riostream.h"
58
59 #endif
60
61
62 // Linked list node for buffer structures.
63 struct AliBufferInfo
64 {
65         AliBufferInfo* fNext;
66         Int_t fEquipId;
67         UInt_t fBufferSize;
68         UChar_t* fBuffer;
69 };
70
71
72 // local structure information to store
73 struct AliLocalStructInfo
74 {
75         UChar_t fId;
76         UChar_t fDec;
77         Bool_t fTrigY;
78         UChar_t fYPos;
79         UChar_t fSXDev;
80         UChar_t fXDev;
81         UChar_t fXPos;
82         Bool_t fTriggerY;
83         Bool_t fTriggerX;
84 };
85
86
87 UInt_t LoadFiles(AliBufferInfo*& list, TString fileName = "./", Int_t maxEvent = 1000)
88 {
89         /// Reads in the DDL files into memory buffers as a linked list.
90
91         AliRawReader* rawReader = AliRawReader::Create(fileName.Data()); 
92
93         if (rawReader == NULL)
94         {
95                 cerr << "ERROR: Could not create AliRawReader." << endl;
96                 delete rawReader;
97                 return 0;
98         }
99
100         UInt_t count = 0;
101         Int_t iEvent = 0;
102         list = NULL;
103         while (rawReader->NextEvent())
104         {
105                 if (iEvent++ >= maxEvent) break;
106
107                 rawReader->Select("MUONTRG", 0, 1);
108                 while (rawReader->ReadHeader())
109                 {
110                         AliBufferInfo* info = new AliBufferInfo;
111                         if (info == NULL)
112                         {
113                                 cerr << "ERROR: Out of memory, sorry. You should limit the number of events read in." << endl;
114                                 delete rawReader;
115                                 return count;
116                         }
117                         info->fNext = list;
118                         info->fEquipId = rawReader->GetEquipmentId();
119                         info->fBufferSize = rawReader->GetDataSize() + sizeof(AliRawDataHeader);
120                         info->fBuffer = new UChar_t[info->fBufferSize];
121                         if (info->fBuffer == NULL)
122                         {
123                                 cerr << "ERROR: Out of memory, sorry. You should limit the number of events read in." << endl;
124                                 delete rawReader;
125                                 return count;
126                         }
127                         list = info;
128                         
129                         // Copy the header.
130                         memcpy(info->fBuffer, rawReader->GetDataHeader(), sizeof(AliRawDataHeader));
131
132                         // Now copy the payload.
133                         if (! rawReader->ReadNext(
134                                                 info->fBuffer + sizeof(AliRawDataHeader),
135                                                 info->fBufferSize - sizeof(AliRawDataHeader)
136                                         )
137                            )
138                         {
139                                 cerr << "ERROR: Failed to read from AliRawReader." << endl;
140                         }
141                         count++;
142                 }
143         }
144
145         delete rawReader;
146         return count;
147 }
148
149
150 UInt_t CountMaxStructs(AliBufferInfo* list)
151 {
152         /// Counts the maximum number of local structures possible
153
154         UInt_t total = 0;
155         AliBufferInfo* current = list;
156         while (current != NULL)
157         {
158                 total += current->fBufferSize / 5;
159                 current = current->fNext;
160         }
161         return total;
162 }
163
164
165 void ReleaseBuffers(AliBufferInfo* list)
166 {
167         /// Deletes the memory allocated for the linked list of buffers.
168
169         AliBufferInfo* current = list;
170         while (current != NULL)
171         {
172                 AliBufferInfo* tmp = current;
173                 current = current->fNext;
174                 delete [] tmp->fBuffer;
175                 delete tmp;
176         }
177 }
178
179
180 Double_t TimeUsingOldDecoder(AliBufferInfo* list, AliLocalStructInfo* buffer, UInt_t maxBufferSize)
181 {
182         /// Perform a timing using the old decoder.
183
184         AliRawReaderMemory rawReader;
185         AliMUONRawStreamTrigger rawStream(&rawReader);
186         rawReader.NextEvent();
187
188         TStopwatch timer;
189         timer.Start(kTRUE);
190
191         UInt_t i = 0;
192         AliBufferInfo* current = list;
193         while (current != NULL)
194         {
195                 rawReader.SetMemory(current->fBuffer, current->fBufferSize);
196                 rawReader.SetEquipmentID(current->fEquipId);
197                 rawReader.Reset();
198
199                 rawStream.First();
200                 
201                 TArrayS fXPattern;
202                 TArrayS fYPattern;
203
204                 while ( rawStream.Next(buffer[i].fId, buffer[i].fDec, buffer[i].fTrigY,
205                                        buffer[i].fYPos, buffer[i].fSXDev, buffer[i].fXDev,
206                                        buffer[i].fXPos, buffer[i].fTriggerY, buffer[i].fTriggerX,
207                                        fXPattern, fYPattern)
208                       )
209                 {
210                         if (i < maxBufferSize-1) i++;
211                 }
212
213                 current = current->fNext;
214         }
215
216         return timer.RealTime();
217 }
218
219
220 Double_t TimeUsingNewDecoder(AliBufferInfo* list, AliLocalStructInfo* buffer, UInt_t maxBufferSize)
221 {
222         /// Perform a timing using the new decoder.
223
224         AliRawReaderMemory rawReader;
225         AliMUONRawStreamTriggerHP rawStream(&rawReader);
226         rawReader.NextEvent();
227
228         TStopwatch timer;
229         timer.Start(kTRUE);
230
231         UInt_t i = 0;
232         AliBufferInfo* current = list;
233         while (current != NULL)
234         {
235                 rawReader.SetMemory(current->fBuffer, current->fBufferSize);
236                 rawReader.SetEquipmentID(current->fEquipId);
237                 rawReader.Reset();
238
239                 rawStream.First();
240
241                 const AliMUONRawStreamTriggerHP::AliLocalStruct* local = NULL;
242                 while ( (local = rawStream.Next()) != NULL )
243                 {
244                         if (i < maxBufferSize)
245                         {
246                                 buffer[i].fId = local->GetId();
247                                 buffer[i].fDec = local->GetDec();
248                                 buffer[i].fTrigY = local->GetTrigY();
249                                 buffer[i].fYPos = local->GetYPos();
250                                 buffer[i].fSXDev = local->GetSXDev();
251                                 buffer[i].fXDev = local->GetXDev();
252                                 buffer[i].fXPos = local->GetXPos();
253                                 buffer[i].fTriggerY = local->GetTriggerY();
254                                 buffer[i].fTriggerX = local->GetTriggerX();
255                                 i++;
256                         }
257                 }
258
259                 current = current->fNext;
260         }
261
262         return timer.RealTime();
263 }
264
265
266 Double_t TimeUsingNewDecoderOldInterface(AliBufferInfo* list, AliLocalStructInfo* buffer, UInt_t maxBufferSize)
267 {
268         /// Perform a timing using the new decoder but the old Next() method
269         /// as the interface.
270
271         AliRawReaderMemory rawReader;
272         AliMUONRawStreamTriggerHP rawStream(&rawReader);
273         rawReader.NextEvent();
274
275         TStopwatch timer;
276         timer.Start(kTRUE);
277
278         UInt_t i = 0;
279         AliBufferInfo* current = list;
280         while (current != NULL)
281         {
282                 rawReader.SetMemory(current->fBuffer, current->fBufferSize);
283                 rawReader.SetEquipmentID(current->fEquipId);
284                 rawReader.Reset();
285
286                 rawStream.First();
287                 
288                 TArrayS fXPattern;
289                 TArrayS fYPattern;
290
291                 while ( rawStream.Next(buffer[i].fId, buffer[i].fDec, buffer[i].fTrigY,
292                                        buffer[i].fYPos, buffer[i].fSXDev, buffer[i].fXDev,
293                                        buffer[i].fXPos, buffer[i].fTriggerY, buffer[i].fTriggerX,
294                                        fXPattern, fYPattern)
295                       )
296                 {
297                         if (i < maxBufferSize-1) i++;
298                 }
299
300                 current = current->fNext;
301         }
302
303         return timer.RealTime();
304 }
305
306
307 void Loop(const char* filename, Bool_t newDecoder)
308 {
309   AliCodeTimerAutoGeneral(Form("Loop %s",(newDecoder ? "NEW":"OLD")),);
310   
311   AliRawReader* reader = AliRawReader::Create(filename);
312   
313   AliMUONVRawStreamTrigger* stream;
314   
315   if ( newDecoder ) 
316   {
317     stream = new AliMUONRawStreamTriggerHP(reader);
318   }
319   else
320   {
321     stream = new AliMUONRawStreamTrigger(reader);
322   }
323
324   UChar_t id;
325   UChar_t dec;
326   Bool_t trigY;
327   UChar_t yPos;
328   UChar_t sXDev;
329   UChar_t xDev;
330   UChar_t xPos;
331   Bool_t triggerY;
332   Bool_t triggerX;
333   TArrayS xPattern;
334   TArrayS yPattern;
335   
336   while ( reader->NextEvent() )
337   {
338     stream->First();
339     
340     while ( stream->Next(id, dec, trigY, yPos, sXDev, xDev, xPos,
341                          triggerY, triggerX, xPattern, yPattern) )
342     {
343       id *= 2;
344     }
345   }
346   
347   delete stream;
348   delete reader;
349 }
350
351
352 void MUONTimeRawStreamTriggerDumb(TString fileName)
353 {
354   AliCodeTimer::Instance()->Reset();
355   
356   // first check we can open the stream
357   AliRawReader* reader = AliRawReader::Create(fileName.Data());
358   if (!reader)
359   {
360     cerr << "Cannot create reader from " << fileName.Data() << endl;
361     return;
362   }
363   delete reader;
364   
365   // now start the timing per se
366   
367   Loop(fileName,kFALSE);
368   
369   Loop(fileName,kTRUE);
370   
371   AliCodeTimer::Instance()->Print();
372 }
373
374
375 void MUONTimeRawStreamTrigger(TString fileName = "./", Int_t maxEvent = 1000)
376 {
377         /// Performs a timing of old and new decoders and reports this.
378
379         AliBufferInfo* list = NULL;
380         UInt_t bufferCount = LoadFiles(list, fileName, maxEvent);
381         if (bufferCount == 0)
382         {
383                 cerr << "ERROR: No DDL files found or read in." << endl;
384                 return;
385         }
386
387         UInt_t maxBufferSize = CountMaxStructs(list);
388         AliLocalStructInfo* buffer = new AliLocalStructInfo[maxBufferSize];
389         if (buffer == NULL)
390         {
391                 ReleaseBuffers(list);
392                 cerr << "ERROR: Out of memory, sorry. You should limit the number of events read in." << endl;
393                 return;
394         }
395         Double_t oldTimes[100];
396         for (Int_t i = 0; i < 100; i++)
397         {
398                 cout << "Timing old decoder: timing iteration " << i+1 << " of 100" << endl;
399                 oldTimes[i] = TimeUsingOldDecoder(list, buffer, maxBufferSize);
400         }
401         Double_t newTimes[100];
402         for (Int_t i = 0; i < 100; i++)
403         {
404                 cout << "Timing new decoder: timing iteration " << i+1 << " of 100" << endl;
405                 newTimes[i] = TimeUsingNewDecoder(list, buffer, maxBufferSize);
406         }
407         Double_t newTimes2[100];
408         for (Int_t i = 0; i < 100; i++)
409         {
410                 cout << "Timing new decoder with old interface: timing iteration " << i+1 << " of 100" << endl;
411                 newTimes2[i] = TimeUsingNewDecoderOldInterface(list, buffer, maxBufferSize);
412         }
413
414         ReleaseBuffers(list);
415         delete buffer;
416
417         Double_t oldTime = TMath::Mean(100, oldTimes) / Double_t(bufferCount);
418         Double_t oldTimeErr = TMath::RMS(100, oldTimes) / Double_t(bufferCount);
419         Double_t newTime = TMath::Mean(100, newTimes) / Double_t(bufferCount);
420         Double_t newTimeErr = TMath::RMS(100, newTimes) / Double_t(bufferCount);
421         Double_t newTime2 = TMath::Mean(100, newTimes2) / Double_t(bufferCount);
422         Double_t newTime2Err = TMath::RMS(100, newTimes2) / Double_t(bufferCount);
423
424         cout << "Average processing time per DDL for:" << endl;
425         cout << "                   Old decoder = " << oldTime*1e6 << " +/- " << oldTimeErr*1e6/TMath::Sqrt(100) << " micro seconds" << endl;
426         cout << "                   New decoder = " << newTime*1e6 << " +/- " << newTimeErr*1e6/TMath::Sqrt(100) << " micro seconds" << endl;
427         cout << "New decoder with old interface = " << newTime2*1e6 << " +/- " << newTime2Err*1e6/TMath::Sqrt(100) << " micro seconds" << endl;
428 }
429