CbmRoot
Loading...
Searching...
No Matches
CbmRecoUnpack.cxx
Go to the documentation of this file.
1/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Volker Friese [committer], Pierre-Alain Loizeau, Pascal Raisig */
9
10
11#include "CbmRecoUnpack.h"
12
13#include "CbmRecoUnpackConfig.tmpl"
14#include "CbmTimeSlice.h"
15#include "CbmTrdDigi.h"
16#include "CbmTsEventHeader.h"
17
18#include <Monitor.hpp>
19#include <System.hpp>
20
21#include <FairRootManager.h>
22#include <Logger.h>
23
24#include <RtypesCore.h>
25#include <TH1.h>
26#include <TStopwatch.h>
27
28#include <cstddef>
29#include <cstdint>
30#include <memory>
31#include <utility>
32#include <vector>
33
34
35using fles::Subsystem;
36using fles::Timeslice;
37using std::unique_ptr;
38
39
40// ----- Constructor ------------------------------------------------------
42// ----------------------------------------------------------------------------
43
44// ----- Destructor ------------------------------------------------------
46{
48 LOG(debug) << "CbmRecoUnpack::~CbmRecoUnpack!";
49};
50// ----------------------------------------------------------------------------
51
52
53// ----- Finish -----------------------------------------------------------
55{
56 LOG(info) << "CbmRecoUnpack::Finish() I do let the unpackers talk first :\n";
57
58 if (fPsdConfig) fPsdConfig->GetUnpacker()->Finish();
59 if (fMuchConfig) fMuchConfig->GetUnpacker()->Finish();
60 if (fRichConfig) fRichConfig->GetUnpacker()->Finish();
61 if (fStsConfig) fStsConfig->GetUnpacker()->Finish();
62 if (fTofConfig) fTofConfig->GetUnpacker()->Finish();
63 if (fTrd1DConfig) fTrd1DConfig->GetUnpacker()->Finish();
64 if (fTrd2DConfig) fTrd2DConfig->GetUnpacker()->Finish();
65 if (fBmonConfig) fBmonConfig->GetUnpacker()->Finish();
66
67 // Create some default performance profiling histograms and write them to a file
69 if (fPublishProfMoni) {
70 double dTotalDataSizeIn = 0.0;
71 double dTotalDataSizeOut = 0.0;
72 for (auto datait : fDataSizeMapCurrSec) {
73 dTotalDataSizeIn += datait.second.first;
74 dTotalDataSizeOut += datait.second.second;
75 }
76 for (auto datait : fDataSizeMapCurrSec) {
77 double dUnpRatio = 0 < datait.second.first ? datait.second.second / datait.second.first : 0.0;
78 double dShareIn = 0 < dTotalDataSizeIn ? datait.second.first / dTotalDataSizeIn : 0.0;
79 double dShareOut = 0 < dTotalDataSizeOut ? datait.second.second / dTotalDataSizeOut : 0.0;
80 fMonitor->QueueMetric(
81 "unpack_perf",
82 {{"host", fMoniCurrrentHostname}, {"jobid", fMoniJobId}, {"det", fNameMapPerTs[datait.first].first}},
83 {{"dataIn", datait.second.first},
84 {"dataOut", datait.second.second},
85 {"unpRatio", dUnpRatio},
86 {"shareIn", dShareIn},
87 {"shareOut", dShareOut}},
88 fPubMoniProcTime ? std::chrono::system_clock::time_point() : fMonitorSecCurrentTs);
89 }
90 }
92}
93
94// ----------------------------------------------------------------------------
95
96// ----- Initialisation ---------------------------------------------------
98{
99
100 FairRootManager* ioman = FairRootManager::Instance();
101 assert(ioman);
102
103 auto eh = FairRun::Instance()->GetEventHeader();
104 if (eh->IsA() == CbmTsEventHeader::Class())
105 fCbmTsEventHeader = static_cast<CbmTsEventHeader*>(eh);
106 else
107 LOG(fatal)
108 << "CbmRecoUnpack::Init() no CbmTsEventHeader was added to the run. Without it, we can not store the UTC of the "
109 "Timeslices correctly. Hence, this causes a fatal. Please add it in the steering macro to the Run.";
110
111 fTimeSlice = new CbmTimeSlice(0., 1.28e8 + 1.28e6); // FIXME: hardcoded TS length + overlap of mCBM 2022 becnhmark
112 ioman->Register("TimeSlice.", "DAQ", fTimeSlice, kTRUE);
113
114 // --- Psd
115 if (fPsdConfig) {
116 fPsdConfig->InitOutput();
118 fPsdConfig->SetAlgo();
119 initParContainers(fPsdConfig->GetParContainerRequest());
120 fPsdConfig->InitAlgo();
121 initPerformanceMaps(Subsystem::PSD, "PSD");
122 if (bSpillFilter) {
123 initSpillFilterMonitoring(Subsystem::PSD, "PSD");
124 }
125 }
126 // --- Rich
127 if (fRichConfig) {
128 fRichConfig->InitOutput();
130 fRichConfig->SetAlgo();
131 initParContainers(fRichConfig->GetParContainerRequest());
132 fRichConfig->InitAlgo();
133 initPerformanceMaps(Subsystem::RICH, "RICH");
134 if (bSpillFilter) {
135 initSpillFilterMonitoring(Subsystem::RICH, "RICH");
136 }
137 }
138
139 // --- Sts
140 if (fStsConfig) {
141 fStsConfig->InitOutput();
143 fStsConfig->SetAlgo();
144 initParContainers(fStsConfig->GetParContainerRequest());
145 fStsConfig->InitAlgo();
146 initPerformanceMaps(Subsystem::STS, "STS");
147 if (bSpillFilter) {
148 initSpillFilterMonitoring(Subsystem::STS, "STS");
149 }
150 }
151
152 // --- Much
153 if (fMuchConfig) {
154 fMuchConfig->InitOutput();
156 fMuchConfig->SetAlgo();
157 initParContainers(fMuchConfig->GetParContainerRequest());
158 fMuchConfig->InitAlgo();
159 initPerformanceMaps(Subsystem::MUCH, "MUCH");
160 if (bSpillFilter) {
161 initSpillFilterMonitoring(Subsystem::MUCH, "MUCH");
162 }
163 }
164
165
166 // --- Tof
167 if (fTofConfig) {
168 fTofConfig->InitOutput();
170 fTofConfig->SetAlgo();
171 fTofConfig->LoadParFileName();
172 initParContainers(fTofConfig->GetParContainerRequest());
173 fTofConfig->InitAlgo();
174 initPerformanceMaps(Subsystem::TOF, "TOF");
175 if (bSpillFilter) {
176 initSpillFilterMonitoring(Subsystem::TOF, "TOF");
177 }
178 }
179 // --- Trd
180 if (fTrd1DConfig) {
181 fTrd1DConfig->InitOutput();
183 fTrd1DConfig->SetAlgo();
184 initParContainers(fTrd1DConfig->GetParContainerRequest());
185 fTrd1DConfig->InitAlgo();
186 initPerformanceMaps(Subsystem::TRD, "TRD1D");
187 if (bSpillFilter) {
188 initSpillFilterMonitoring(Subsystem::TRD, "TRD1D");
189 }
190 }
191 // --- TRD2D
192 if (fTrd2DConfig) {
193 if (fTrd1DConfig && (fTrd2DConfig->GetOutputBranchName() == fTrd1DConfig->GetOutputBranchName())) {
194 LOG(info) << fTrd2DConfig->GetName() << "::Init() ---------------------------------";
195 fTrd2DConfig->SetOutputVec(fTrd1DConfig->GetOutputVec());
196 }
197 else {
198 fTrd2DConfig->InitOutput();
200 }
201 fTrd2DConfig->SetAlgo();
202 initParContainers(fTrd2DConfig->GetParContainerRequest());
203 fTrd2DConfig->InitAlgo();
204 initPerformanceMaps(Subsystem::TRD2D, "TRD2D");
205 if (bSpillFilter) {
206 initSpillFilterMonitoring(Subsystem::TRD2D, "TRD2D");
207 }
208 }
209 // This is an ugly work around, because the TRD and TRD2D want to access the same vector and there is no
210 // function to retrieve a writeable vector<obj> from the FairRootManager, especially before the branches
211 // are created, as far as I am aware.
212 // The second option workaround is in in Init() to look for the fasp config and create a separate branch
213 // for fasp created CbmTrdDigis PR 072021
214
215 // --- Bmon
216 if (fBmonConfig) {
217 fBmonConfig->InitOutput();
219 fBmonConfig->SetAlgo();
220 fBmonConfig->LoadParFileName();
221 initParContainers(fBmonConfig->GetParContainerRequest());
222 fBmonConfig->InitAlgo();
223 initPerformanceMaps(Subsystem::BMON, "Bmon");
224 if (bSpillFilter) {
225 initSpillFilterMonitoring(Subsystem::BMON, "Bmon");
226 }
227 }
228
229 if (bSpillFilter) {
230 // No return value but will set bSpillFilter back to false if failing (to be equivalent to old implementation)
232 }
233
234 if (fDoPerfProfPerTs) {
236 fTimerTs = new TStopwatch();
237
238 fhCpuTimePerTs = new TH1D("hCpuTimePerTs", "CPU Processing time of TS vs TS; Ts; CPU time [ms]", 6000, 0, 6000);
239 fhRealTimePerTs = new TH1D("hRealTimePerTs", "Real Processing time of TS vs TS; Ts; Real time [ms]", 6000, 0, 6000);
240
242 new TH1D("hCpuTimePerTsHist", "CPU Histo filling time of TS vs TS; Ts; CPU time [ms]", 6000, 0, 6000);
244 new TH1D("hRealTimePerTsHist", "Real Histo filling time of TS vs TS; Ts; Real time [ms]", 6000, 0, 6000);
245
247 new TH1D("hUnpackingRatioPerTs", "ratio of tot. unp. digi size to tot. input raw size vs TS; TS; Size Ratio []",
248 6000, 0, 6000);
249 }
250
251 if (fPublishProfMoni) { //
252 fMonitor = std::make_unique<cbm::Monitor>(fUriPublishProfMoni);
253 fMoniCurrrentHostname = fles::system::current_hostname();
254 LOG(info) << "Unpack: Publishing monitoring metrics to time-series DB at " << fUriPublishProfMoni << " as "
255 << fMoniCurrrentHostname << " with job ID " << fMoniJobId;
256 }
257
258 return kTRUE;
259}
260// ----------------------------------------------------------------------------
261
262// ----- initSpillFilterMonitoring ----------------------------------------
264{
266 std::ifstream ifsRaw(sAccEvtTimingFile);
267
268 if (ifsRaw.is_open()) {
270 std::string sLine;
271 while (std::getline(ifsRaw, sLine)) {
273 if ("\n" != sLine) {
274 AccTimingEvent newEvent(sLine);
275 if (newEvent.IsExtractionStart() || newEvent.IsKickerStart()) {
276 vAccEvtsSpillStart.push_back(newEvent);
277 }
278 else if (newEvent.IsExtractionEnd() || newEvent.IsExtractionStopSlow()) {
279 vAccEvtsSpillEnd.push_back(newEvent);
280 }
281 }
282 }
283 LOG(info) << "Accelerator events file " << sAccEvtTimingFile << " processed";
284 if (0 == vAccEvtsSpillStart.size()) {
285 LOG(error) << "No spill start events found in file " << sAccEvtTimingFile << " => Disabling filtering!";
286 bSpillFilter = false;
287 return;
288 }
289 if (0 == vAccEvtsSpillEnd.size()) {
290 LOG(error) << "No spill stop events found in file " << sAccEvtTimingFile << " => Disabling filtering!";
291 bSpillFilter = false;
292 return;
293 }
296 }
297 else {
298 LOG(error) << "Accelerator events file " << sAccEvtTimingFile << " could not be open! => Disabling filtering!";
299 bSpillFilter = false;
300 return;
301 }
302 int32_t iWindowNbBinsNs = std::round(dSpillFilterWinStop - dSpillFilterWinStart);
303 int32_t iWindowNbBinsFewNs = std::round((dSpillFilterWinStop - dSpillFilterWinStart) / 10);
305 fhDigiSpillStartDist = new TH1D("hDigiSpillStartDist", "Digi time vs spill start time; Tdigi - Tspill_start [ns]",
306 20000, -100000., 100000);
308 new TH1D("hDigiSpillStopist", "Digi time vs spill stop time; Tdigi - Tspill_stop [ns]", 20000, -100000., 100000);
309 }
310 else {
311 fhDigiSpillStartDist = new TH1D("hDigiSpillStartDist", "Digi time vs spill start time; Tdigi - Tspill_start [ns]",
312 iWindowNbBinsFewNs, dSpillFilterWinStart, dSpillFilterWinStop);
313 fhDigiSpillStopDist = new TH1D("hDigiSpillStopDist", "Digi time vs spill stop time; Tdigi - Tspill_stop [ns]",
314 iWindowNbBinsFewNs, dSpillFilterWinStart, dSpillFilterWinStop);
315 }
317 new TH2D("hDigiSpillFilterStart", "Digi time vs spill start time, per spill; Tdigi - Tspill_start [ns]; Spill",
318 iWindowNbBinsNs, dSpillFilterWinStart, dSpillFilterWinStop, 1000, 0., 1000.);
320 new TH2D("hDigiSpillFilterStop", "Digi time vs spill stop time, per spill; Tdigi - Tspill_stop [ns]; Spill",
321 iWindowNbBinsNs, dSpillFilterWinStart, dSpillFilterWinStop, 1000, 0., 1000.);
322}
323// ----------------------------------------------------------------------------
324
325// ----- initSpillFilterMonitoring ----------------------------------------
327{
328 int32_t iWindowNbBinsNs = std::round(dSpillFilterWinStop - dSpillFilterWinStart);
329 int32_t iWindowNbBinsFewNs = std::round((dSpillFilterWinStop - dSpillFilterWinStart) / 10);
331 fhDigiSpillStartDistPerDet.emplace(std::make_pair(
332 subsystem, new TH1D(Form("hDigiSpillStartDist%s", name.c_str()),
333 Form("Digi time vs spill start time, for %s; Tdigi - Tspill_start [ns]", name.c_str()), 20000,
334 -100000., 100000)));
335 fhDigiSpillStopDistPerDet.emplace(std::make_pair(
336 subsystem, new TH1D(Form("hDigiSpillStopDist%s", name.c_str()),
337 Form("Digi time vs spill stop time, for %s; Tdigi - Tspill_stop [ns]", name.c_str()), 20000,
338 -100000., 100000)));
339 }
340 else {
341 fhDigiSpillStartDistPerDet.emplace(std::make_pair(
342 subsystem, new TH1D(Form("hDigiSpillStartDist%s", name.c_str()),
343 Form("Digi time vs spill start time, for %s; Tdigi - Tspill_start [ns]", name.c_str()),
344 iWindowNbBinsFewNs, dSpillFilterWinStart, dSpillFilterWinStop)));
345 fhDigiSpillStopDistPerDet.emplace(std::make_pair(
346 subsystem, new TH1D(Form("hDigiSpillStopDist%s", name.c_str()),
347 Form("Digi time vs spill stop time, for %s; Tdigi - Tspill_stop [ns]", name.c_str()),
348 iWindowNbBinsFewNs, dSpillFilterWinStart, dSpillFilterWinStop)));
349 }
350 fhDigiSpillFilterStartPerDet.emplace(std::make_pair(
351 subsystem,
352 new TH2D(Form("hDigiSpillStart%s", name.c_str()),
353 Form("Digi time vs spill start time, per spill for %s; Tdigi - Tspill_start [ns]; Spill", name.c_str()),
354 iWindowNbBinsNs, dSpillFilterWinStart, dSpillFilterWinStop, 1000, 0., 1000.)));
355 fhDigiSpillFilterStopPerDet.emplace(std::make_pair(
356 subsystem,
357 new TH2D(Form("hDigiSpillStop%s", name.c_str()),
358 Form("Digi time vs spill stop time, per spill for %s; Tdigi - Tspill_stop [ns]; Spill", name.c_str()),
359 iWindowNbBinsNs, dSpillFilterWinStart, dSpillFilterWinStop, 1000, 0., 1000.)));
360}
361// ----------------------------------------------------------------------------
362
363
364// ----- initPerformanceMaps ----------------------------------------------
365void CbmRecoUnpack::initPerformanceMaps(Subsystem subsystem, std::string name)
366{
367 if (fDoPerfProf) {
368 fNameMap.emplace(std::make_pair(subsystem, std::make_pair(name, 0)));
369 fTimeMap.emplace(std::make_pair(subsystem, std::make_pair(0, 0)));
370 fDataSizeMap.emplace(std::make_pair(subsystem, std::make_pair(0, 0)));
371 }
372 if (fDoPerfProfPerTs) {
373 fNameMapPerTs.emplace(std::make_pair(subsystem, std::make_pair(name, 0)));
374 fTimeMapPerTs.emplace(std::make_pair(subsystem, std::make_pair(0, 0)));
375 fDataSizeMapPerTs.emplace(std::make_pair(subsystem, std::make_pair(0, 0)));
376 if (fPublishProfMoni) { //
377 fDataSizeMapCurrSec.emplace(std::make_pair(subsystem, std::make_pair(0, 0)));
378 }
379
380 fvhInpRatioPerTs.emplace(std::make_pair(
381 subsystem,
382 new TH1D(Form("hInpRatioPerTs%s", name.c_str()),
383 Form("ratio of input data size in total input data size vs TS for %s; TS; Size Ratio []", name.c_str()),
384 6000, 0, 6000)));
385 fvhOutRatioPerTs.emplace(std::make_pair(
386 subsystem,
387 new TH1D(Form("hOutRatioPerTs%s", name.c_str()),
388 Form("ratio of unpacked digi size in total output size vs TS for %s; TS; Size Ratio []", name.c_str()),
389 6000, 0, 6000)));
390 fvhUnpRatioPerTs.emplace(std::make_pair(
391 subsystem,
392 new TH1D(Form("hUnpRatioPerTs%s", name.c_str()),
393 Form("ratio of unpacked digi size to raw data size vs TS for %s; TS; O/I Size Ratio []", name.c_str()),
394 6000, 0, 6000)));
395 }
396}
397// ----------------------------------------------------------------------------
398
399
400// ----- performanceProfiling ---------------------------------------------
402{
403 hProducedDigis = new TH1D("ProducedDigis", "ProducedDigis", fNameMap.size(), -0.5, fNameMap.size() - 0.5);
404 hProducedDigis->SetXTitle("Subsystem");
405 hProducedDigis->SetYTitle("N-Digis");
406 hSpeedPerf = new TH1D("SpeedPerformance", "SpeedPerformance", fNameMap.size() * 2, -0.5, fNameMap.size() * 2 - 0.5);
407 hSpeedPerf->SetXTitle("Subsystem");
408 hSpeedPerf->SetYTitle("Unpacking performance [#mus/Digi]");
409 hDataPerf = new TH1D("DataPerformance", "DataPerformance", fNameMap.size() * 2, -0.5, fNameMap.size() * 2 - 0.5);
410 hDataPerf->SetXTitle("Subsystem");
411 hDataPerf->SetYTitle("Data [MB]");
412 size_t iunpackerbin = 1;
413 for (auto namepair : fNameMap) {
414
415 // Speed performance
416 auto timeit = fTimeMap.find(namepair.first);
417 double cpu = 0 < namepair.second.second ? timeit->second.first / namepair.second.second : 0.0;
418 double wall = 0 < namepair.second.second ? timeit->second.second / namepair.second.second : 0.0;
419
420 // Data performance
421 auto datait = fDataSizeMap.find(namepair.first);
422 double indata = datait->second.first;
423 double outdata = datait->second.second;
424
425
426 // N-Digis
427 std::string label = namepair.second.first;
428 hProducedDigis->GetXaxis()->SetBinLabel(iunpackerbin, label.data());
429 hProducedDigis->SetBinContent(iunpackerbin, namepair.second.second);
430
431 // Cpu time
432 label = namepair.second.first;
433 label += " cpu";
434 hSpeedPerf->GetXaxis()->SetBinLabel(iunpackerbin * 2 - 1, label.data());
435 hSpeedPerf->SetBinContent(iunpackerbin * 2 - 1, cpu);
436 // Wall time
437 label = namepair.second.first;
438 label += " wall";
439 hSpeedPerf->GetXaxis()->SetBinLabel(iunpackerbin * 2, label.data());
440 hSpeedPerf->SetBinContent(iunpackerbin * 2, wall);
441
442 // In data
443 label = namepair.second.first;
444 label += " in";
445 hDataPerf->GetXaxis()->SetBinLabel(iunpackerbin * 2 - 1, label.data());
446 hDataPerf->SetBinContent(iunpackerbin * 2 - 1, indata);
447
448 // Out data
449 label = namepair.second.first;
450 label += " out";
451 hDataPerf->GetXaxis()->SetBinLabel(iunpackerbin * 2, label.data());
452 hDataPerf->SetBinContent(iunpackerbin * 2, outdata);
453
454 ++iunpackerbin;
455 }
456}
458{
460 double dTotalCpuTime = fTimerTs->CpuTime() * 1000.;
461 double dTotalRealTime = fTimerTs->RealTime() * 1000.;
462 fTimerTs->Start();
463
464 /*
465 for (auto timeit : fTimeMapPerTs) {
466 // Speed performance
467 dTotalCpuTime += timeit->second.first
468 dTotalRealTime += timeit->second.second
469 }
470 */
471
472 double dTotalDataSizeIn = 0.0;
473 double dTotalDataSizeOut = 0.0;
474
475 using sctp = std::chrono::system_clock::time_point;
476 sctp tsStart = sctp(std::chrono::seconds(static_cast<uint64_t>(fCbmTsEventHeader->GetTsStartTime() * 1e-9)));
477 if (fMonitorSecCurrentTs == sctp()) { //
478 fMonitorSecCurrentTs = tsStart;
479 }
480 else if (fPubMoniProcTime || fMonitorSecCurrentTs < tsStart) {
481 for (auto datait : fDataSizeMapCurrSec) {
482 dTotalDataSizeIn += datait.second.first;
483 dTotalDataSizeOut += datait.second.second;
484 }
485 for (auto datait : fDataSizeMapCurrSec) {
486 double dUnpRatio = 0 < datait.second.first ? datait.second.second / datait.second.first : 0.0;
487 double dShareIn = 0 < dTotalDataSizeIn ? datait.second.first / dTotalDataSizeIn : 0.0;
488 double dShareOut = 0 < dTotalDataSizeOut ? datait.second.second / dTotalDataSizeOut : 0.0;
489 fMonitor->QueueMetric(
490 "unpack_perf",
491 {{"host", fMoniCurrrentHostname}, {"jobid", fMoniJobId}, {"det", fNameMapPerTs[datait.first].first}},
492 {{"dataIn", datait.second.first},
493 {"dataOut", datait.second.second},
494 {"unpRatio", dUnpRatio},
495 {"shareIn", dShareIn},
496 {"shareOut", dShareOut}},
498 }
499 fMonitorSecCurrentTs = tsStart;
500 for (auto datait = fDataSizeMapCurrSec.begin(); datait != fDataSizeMapCurrSec.end(); ++datait) {
501 datait->second.first = 0.0;
502 datait->second.second = 0.0;
503 }
504 dTotalDataSizeIn = 0.0;
505 dTotalDataSizeOut = 0.0;
506 }
507
509 for (auto datait : fDataSizeMapPerTs) {
510 dTotalDataSizeIn += datait.second.first;
511 dTotalDataSizeOut += datait.second.second;
512
513 if (fPublishProfMoni) {
514 fDataSizeMapCurrSec[datait.first].first += datait.second.first;
515 fDataSizeMapCurrSec[datait.first].second += datait.second.second;
516 }
517 }
518 for (auto datait : fDataSizeMapPerTs) {
519 fvhInpRatioPerTs[datait.first]->Fill(fCbmTsEventHeader->GetTsIndex(), datait.second.first / dTotalDataSizeIn);
520 fvhOutRatioPerTs[datait.first]->Fill(fCbmTsEventHeader->GetTsIndex(), datait.second.second / dTotalDataSizeOut);
521 if (datait.second.first) { //
522 fvhUnpRatioPerTs[datait.first]->Fill(fCbmTsEventHeader->GetTsIndex(), datait.second.second / datait.second.first);
523 }
524 }
525 fhUnpackingRatioPerTs->Fill(fCbmTsEventHeader->GetTsIndex(), dTotalDataSizeOut / dTotalDataSizeIn);
526 fhCpuTimePerTs->Fill(fCbmTsEventHeader->GetTsIndex(), dTotalCpuTime);
527 fhRealTimePerTs->Fill(fCbmTsEventHeader->GetTsIndex(), dTotalRealTime);
528
529 for (auto timeit = fTimeMapPerTs.begin(); timeit != fTimeMapPerTs.end(); ++timeit) {
530 // Speed performance
531 timeit->second.first = 0.0;
532 timeit->second.second = 0.0;
533 }
534 for (auto datait = fDataSizeMapPerTs.begin(); datait != fDataSizeMapPerTs.end(); ++datait) {
535 datait->second.first = 0.0;
536 datait->second.second = 0.0;
537 }
538
539 fTimerTs->Stop();
540 fhCpuTimePerTsHist->Fill(fCbmTsEventHeader->GetTsIndex(), fTimerTs->CpuTime() * 1000.);
541 fhRealTimePerTsHist->Fill(fCbmTsEventHeader->GetTsIndex(), fTimerTs->RealTime() * 1000.);
542}
543// ----------------------------------------------------------------------------
544
546{
548 TFile* oldFile = gFile;
549 TDirectory* oldDir = gDirectory;
550
552 TFile histofile(fOutfilename.data(), "RECREATE");
553
554 histofile.cd();
555 if (fDoPerfProf) {
556 hProducedDigis->Write();
557 hSpeedPerf->Write();
558 hDataPerf->Write();
559 if (fDoPerfProfPerTs) {
560 fhCpuTimePerTs->Write();
561 fhRealTimePerTs->Write();
562 fhCpuTimePerTsHist->Write();
563 fhRealTimePerTsHist->Write();
564 for (auto detHist : fvhInpRatioPerTs) {
565 fvhInpRatioPerTs[detHist.first]->Write();
566 fvhOutRatioPerTs[detHist.first]->Write();
567 fvhUnpRatioPerTs[detHist.first]->Write();
568 }
569 fhUnpackingRatioPerTs->Write();
570 }
571 }
572
573 if (bSpillFilter) {
575 fhDigiSpillStartDist->Write();
576 fhDigiSpillStopDist->Write();
577 fhDigiSpillFilterStart->Write();
578 fhDigiSpillFilterStop->Write();
579 for (auto detHist : fhDigiSpillFilterStartPerDet) {
580 fhDigiSpillStartDistPerDet[detHist.first]->Write();
581 fhDigiSpillStopDistPerDet[detHist.first]->Write();
582 fhDigiSpillFilterStartPerDet[detHist.first]->Write();
583 fhDigiSpillFilterStopPerDet[detHist.first]->Write();
584 }
585 }
586
588 gFile = oldFile;
589 gDirectory = oldDir;
590
591 histofile.Close();
592}
593
594// ----- Reset ------------------------------------------------------------
596{
597 // Reset the event header for a new timeslice
598 fCbmTsEventHeader->Reset();
599 fTimeSlice->Reset(0., 1.28e8 + 1.28e6); // FIXME: hardcoded TS length + overlap of mCBM 2022 becnhmark
600
601 // Reset the unpackers for a new timeslice, e.g. clear the output vectors
602
603 // ----Much ----
604 if (fMuchConfig) fMuchConfig->Reset();
605 // ---- Psd ----
606 if (fPsdConfig) fPsdConfig->Reset();
607 // ---- Rich ----
608 if (fRichConfig) fRichConfig->Reset();
609 // ---- Sts ----
610 if (fStsConfig) fStsConfig->Reset();
611 // ---- Tof ----
612 if (fTofConfig) fTofConfig->Reset();
613 // ---- Trd ----
614 if (fTrd1DConfig) fTrd1DConfig->Reset();
615 // ---- Trd2D ----
616 if (fTrd2DConfig) fTrd2DConfig->Reset();
617 // ---- Bmon ----
618 if (fBmonConfig) fBmonConfig->Reset();
619}
620
621// ----------------------------------------------------------------------------
622
623// ----- Unpacking --------------------------------------------------------
624void CbmRecoUnpack::Unpack(unique_ptr<Timeslice> ts)
625{
626 if (fDoPerfProfPerTs) {
628 fTimerTs->Start();
629 }
630
631 // Prepare timeslice
632 const fles::Timeslice& timeslice = *ts;
633
634 fCbmTsEventHeader->SetTsIndex(ts->index());
635 fCbmTsEventHeader->SetTsStartTime(ts->start_time());
636
637 fTimeSlice->SetStartTime(ts->start_time());
638
639 uint64_t nComponents = ts->num_components();
640 if (fDoDebugPrints || 0 == ts->index() % 100) {
641 LOG(info) << "Unpack: TS index " << ts->index() << " components " << nComponents;
642 }
643
644 for (uint64_t component = 0; component < nComponents; component++) {
645
646 auto subsystem = static_cast<Subsystem>(ts->descriptor(component, 0).sys_id);
647
648 switch (subsystem) {
649 case Subsystem::MUCH: {
650 if (fMuchConfig) {
651 fCbmTsEventHeader->AddNDigisMuch(unpack(subsystem, &timeslice, component, fMuchConfig,
652 fMuchConfig->GetOptOutAVec(), fMuchConfig->GetOptOutBVec()));
653 }
654 break;
655 }
656
657 case Subsystem::PSD: {
658 if (fPsdConfig) {
659 fCbmTsEventHeader->AddNDigisPsd(unpack(subsystem, &timeslice, component, fPsdConfig,
660 fPsdConfig->GetOptOutAVec(), fPsdConfig->GetOptOutBVec()));
661 }
662 break;
663 }
664 case Subsystem::RICH: {
665 if (fRichConfig) {
666 fCbmTsEventHeader->AddNDigisRich(unpack(subsystem, &timeslice, component, fRichConfig,
667 fRichConfig->GetOptOutAVec(), fRichConfig->GetOptOutBVec()));
668 }
669 break;
670 }
671 case Subsystem::STS: {
672 if (fStsConfig) {
673 fCbmTsEventHeader->AddNDigisSts(unpack(subsystem, &timeslice, component, fStsConfig,
674 fStsConfig->GetOptOutAVec(), fStsConfig->GetOptOutBVec()));
675 }
676 break;
677 }
678 case Subsystem::TOF: {
679 if (fTofConfig) {
680 fCbmTsEventHeader->AddNDigisTof(unpack(subsystem, &timeslice, component, fTofConfig,
681 fTofConfig->GetOptOutAVec(), fTofConfig->GetOptOutBVec()));
682 }
683 break;
684 }
685 case Subsystem::TRD: {
686 if (fTrd1DConfig) {
687 fCbmTsEventHeader->AddNDigisTrd1D(unpack(subsystem, &timeslice, component, fTrd1DConfig,
688 fTrd1DConfig->GetOptOutAVec(), fTrd1DConfig->GetOptOutBVec()));
689 }
690 break;
691 }
692 case Subsystem::TRD2D: {
693 if (fTrd2DConfig) {
694 fCbmTsEventHeader->AddNDigisTrd2D(unpack(subsystem, &timeslice, component, fTrd2DConfig,
695 fTrd2DConfig->GetOptOutAVec(), fTrd2DConfig->GetOptOutBVec()));
696 }
697 break;
698 }
699 case Subsystem::BMON: {
700 if (fBmonConfig) {
701 fCbmTsEventHeader->AddNDigisBmon(unpack(subsystem, &timeslice, component, fBmonConfig,
702 fBmonConfig->GetOptOutAVec(), fBmonConfig->GetOptOutBVec()));
703 }
704 break;
705 }
706 default: {
707 if (fDoDebugPrints)
708 LOG(error) << "Unpack: Unknown subsystem " << fles::to_string(subsystem) << " for component " << component;
709 break;
710 }
711 }
712 }
713
716 if (fMuchConfig && fMuchConfig->GetOutputVec()) {
717 timesort(fMuchConfig->GetOutputVec());
718 }
719 if (fPsdConfig && fPsdConfig->GetOutputVec()) {
720 timesort(fPsdConfig->GetOutputVec());
721 }
722 if (fRichConfig && fRichConfig->GetOutputVec()) {
723 timesort(fRichConfig->GetOutputVec());
724 }
725 if (fStsConfig && fStsConfig->GetOutputVec()) {
726 timesort(fStsConfig->GetOutputVec());
727 }
728 if (fTofConfig && fTofConfig->GetOutputVec()) {
729 timesort(fTofConfig->GetOutputVec());
730 }
731 if (fTrd1DConfig && fTrd1DConfig->GetOutputVec()) {
732 timesort(fTrd1DConfig->GetOutputVec());
733 }
734 if (fTrd2DConfig && fTrd2DConfig->GetOutputVec()) {
735 timesort(fTrd2DConfig->GetOutputVec());
736 }
737 if (fBmonConfig && fBmonConfig->GetOutputVec()) {
738 timesort(fBmonConfig->GetOutputVec());
739 }
740
742 if (fMuchConfig && fMuchConfig->GetOptOutAVec()) {
743 timesort(fMuchConfig->GetOptOutAVec());
744 }
745 if (fPsdConfig && fPsdConfig->GetOptOutAVec()) {
746 timesort(fPsdConfig->GetOptOutAVec());
747 }
748 if (fRichConfig && fRichConfig->GetOptOutAVec()) {
749 timesort(fRichConfig->GetOptOutAVec());
750 }
751 if (fStsConfig && fStsConfig->GetOptOutAVec()) {
752 timesort(fStsConfig->GetOptOutAVec());
753 }
754 if (fTofConfig && fTofConfig->GetOptOutAVec()) {
755 timesort(fTofConfig->GetOptOutAVec());
756 }
757 if (fTrd1DConfig && fTrd1DConfig->GetOptOutAVec()) {
758 timesort(fTrd1DConfig->GetOptOutAVec());
759 }
760 if (fTrd2DConfig && fTrd2DConfig->GetOptOutAVec()) {
761 timesort(fTrd2DConfig->GetOptOutAVec());
762 }
763 if (fBmonConfig && fBmonConfig->GetOptOutAVec()) {
764 timesort(fBmonConfig->GetOptOutAVec());
765 }
766 }
767
768 if (fBmonConfig && fBmonConfig->GetMonitor()) { //
769 fBmonConfig->GetMonitor()->FinalizeTsBmonMicroSpillHistos();
770 fBmonConfig->GetMonitor()->FinalizeTsBmonQfactorHistos(ts->start_time(), fBmonConfig->GetOutputVec());
771 }
772
773 if (fTofConfig && fTofConfig->GetMonitor()) { //
774 fTofConfig->GetMonitor()->FinalizeTsHistos(ts->start_time());
775 }
776
777 if (bSpillFilter) {
781 uint64_t uTimeDistNs = std::numeric_limits<uint64_t>::max();
782 while (itSpillStart != vAccEvtsSpillStart.end()) {
783 uint64_t uNewTimeDistNs = 0;
784 if (itSpillStart->GetTime() < ts->start_time()) {
785 uNewTimeDistNs = ts->start_time() - itSpillStart->GetTime();
786 }
787 else {
788 uNewTimeDistNs = itSpillStart->GetTime() - ts->start_time();
789 }
790 if (uTimeDistNs < uNewTimeDistNs) {
792 break;
793 }
794 uTimeDistNs = uNewTimeDistNs;
795 itSpillStart++;
796 }
797 --itSpillStart; // Valid even if end reached as check for at least one event in Init
798
799 LOG(info) << "Found spill start for ts " << ts->start_time() << ": " << itSpillStart->GetTime() << " ("
800 << uTimeDistNs << ")";
801
803 uTimeDistNs = std::numeric_limits<uint64_t>::max();
804 while (itSpillStop != vAccEvtsSpillEnd.end()) {
805 uint64_t uNewTimeDistNs = 0;
806 if (itSpillStop->GetTime() < ts->start_time()) {
807 uNewTimeDistNs = ts->start_time() - itSpillStop->GetTime();
808 }
809 else {
810 uNewTimeDistNs = itSpillStop->GetTime() - ts->start_time();
811 }
812 if (uTimeDistNs < uNewTimeDistNs) {
814 break;
815 }
816 uTimeDistNs = uNewTimeDistNs;
817 itSpillStop++;
818 }
819 --itSpillStop; // Valid even if end reached as check for at least one event in Init
820
821 LOG(info) << "Found spill stop for ts " << ts->start_time() << ": " << itSpillStop->GetTime() << " ("
822 << uTimeDistNs << ")";
823 }
824 else {
827 uint64_t uTimeDistNs = 0;
828 std::string sSignCurr;
829 if (itSpillStart->GetTime() < ts->start_time()) {
830 uTimeDistNs = ts->start_time() - itSpillStart->GetTime();
831 sSignCurr = "-";
832 }
833 else {
834 uTimeDistNs = itSpillStart->GetTime() - ts->start_time();
835 sSignCurr = "+";
836 }
837 auto itSpillStartNext = itSpillStart + 1;
838 uint64_t uNextTimeDistNs = 0;
839 std::string sSignCurrNext;
840 if (itSpillStartNext->GetTime() < ts->start_time()) {
841 uNextTimeDistNs = ts->start_time() - itSpillStartNext->GetTime();
842 sSignCurrNext = "-";
843 }
844 else {
845 uNextTimeDistNs = itSpillStartNext->GetTime() - ts->start_time();
846 sSignCurrNext = "+";
847 }
848 if (uNextTimeDistNs < uTimeDistNs) {
849 LOG(debug) << "New spill start for ts " << ts->start_time() << ": " << itSpillStart->GetTime() << " ("
850 << sSignCurr << uTimeDistNs << ") " << itSpillStartNext->GetTime() << " (" << sSignCurrNext
851 << uNextTimeDistNs << ") ";
852 itSpillStart = itSpillStartNext;
853 uSpillIndex++;
854 }
855 else {
856 LOG(debug) << "Curr spill start for ts " << ts->start_time() << ": " << itSpillStart->GetTime() << " ("
857 << sSignCurr << uTimeDistNs << ") " << itSpillStartNext->GetTime() << " (" << sSignCurrNext
858 << uNextTimeDistNs << ") ";
859 }
860
861 uTimeDistNs = 0;
862 if (itSpillStop->GetTime() < ts->start_time()) {
863 uTimeDistNs = ts->start_time() - itSpillStop->GetTime();
864 sSignCurr = "-";
865 }
866 else {
867 uTimeDistNs = itSpillStop->GetTime() - ts->start_time();
868 sSignCurr = "+";
869 }
870 auto itSpillStopNext = itSpillStop + 1;
871 uNextTimeDistNs = 0;
872 if (itSpillStopNext->GetTime() < ts->start_time()) {
873 uNextTimeDistNs = ts->start_time() - itSpillStopNext->GetTime();
874 sSignCurrNext = "-";
875 }
876 else {
877 uNextTimeDistNs = itSpillStopNext->GetTime() - ts->start_time();
878 sSignCurrNext = "+";
879 }
880 if (uNextTimeDistNs < uTimeDistNs) {
881 LOG(debug) << "New spill stop for ts " << ts->start_time() << ": " << itSpillStop->GetTime() << " ("
882 << sSignCurr << uTimeDistNs << ") " << itSpillStopNext->GetTime() << " (" << sSignCurrNext
883 << uNextTimeDistNs << ") ";
884 itSpillStop = itSpillStopNext;
885 }
886 else {
887 LOG(debug) << "Curr spill stop for ts " << ts->start_time() << ": " << itSpillStop->GetTime() << " ("
888 << sSignCurr << uTimeDistNs << ") " << itSpillStopNext->GetTime() << " (" << sSignCurrNext
889 << uNextTimeDistNs << ") ";
890 }
891 }
892
893 if (fMuchConfig && fMuchConfig->GetOutputVec()) {
894 SpillFilter(ts->start_time(), Subsystem::MUCH, fMuchConfig->GetOutputVec());
895 }
896 if (fPsdConfig && fPsdConfig->GetOutputVec()) {
897 SpillFilter(ts->start_time(), Subsystem::PSD, fPsdConfig->GetOutputVec());
898 }
899 if (fRichConfig && fRichConfig->GetOutputVec()) {
900 SpillFilter(ts->start_time(), Subsystem::RICH, fRichConfig->GetOutputVec());
901 }
902 if (fStsConfig && fStsConfig->GetOutputVec()) {
903 SpillFilter(ts->start_time(), Subsystem::STS, fStsConfig->GetOutputVec());
904 }
905 if (fTofConfig && fTofConfig->GetOutputVec()) {
906 SpillFilter(ts->start_time(), Subsystem::TOF, fTofConfig->GetOutputVec());
907 }
908 if (fTrd1DConfig && fTrd1DConfig->GetOutputVec()) {
909 SpillFilter(ts->start_time(), Subsystem::TRD, fTrd1DConfig->GetOutputVec());
910 }
911 if (fTrd2DConfig && fTrd2DConfig->GetOutputVec()) {
912 SpillFilter(ts->start_time(), Subsystem::TRD2D, fTrd2DConfig->GetOutputVec());
913 }
914 if (fBmonConfig && fBmonConfig->GetOutputVec()) {
915 SpillFilter(ts->start_time(), Subsystem::BMON, fBmonConfig->GetOutputVec());
916 }
917 }
918
919 if (fDoPerfProfPerTs) {
920 fTimerTs->Stop();
922 }
923}
924// ----------------------------------------------------------------------------
925
ClassImp(CbmConverterManager)
bool Bool_t
bool IsExtractionEnd() const
bool IsKickerStart() const
bool IsExtractionStart() const
bool IsExtractionStopSlow() const
Main steering class for unpacking in cbmroot.
virtual Bool_t initParContainers(std::vector< std::pair< std::string, std::shared_ptr< FairParGenericSet > > > *reqparvec)
Initialise the parameter containers requested by the algorithm.
void Finish()
Actions at the end of the run.
std::unique_ptr< cbm::Monitor > fMonitor
ratio of total unpacked size to input size vs TS in run
CbmTimeSlice * fTimeSlice
CbmTimeslice object, mostly redundant with the TsEventHeader, needed by L1 to switch timeslice mode.
double_t dSpillFilterWinStart
Start of time window for digi filtering relative to spill start event.
TH1 * fhDigiSpillStartDist
Monitoring histograms for the spill digi filter.
std::string fUriPublishProfMoni
URI (type:hostname:port:db_name) for optional connection to monitoring DB.
TH2 * fhDigiSpillFilterStop
Digi time relative to spill start.
std::map< Subsystem, TH2 * > fhDigiSpillFilterStartPerDet
Digi time relative to spill stop, per detector.
CbmRecoUnpack()
Constructor.
std::map< Subsystem, TH1 * > fvhUnpRatioPerTs
ratio of system digi size in total output size vs TS in run
bool fPublishProfMoni
Flag if performance profiling data should be published to monitoring DB.
size_t unpack(const Subsystem subsystem, const fles::Timeslice *ts, uint16_t icomp, TConfig config, std::vector< TOptOutA > *optouttargetvecA=nullptr, std::vector< TOptOutB > *optouttargetvecB=nullptr)
Template for the unpacking call of a given algorithm.
std::string fMoniJobId
double_t dSpillFilterWinStop
End of time window for digi filtering relative to spill start event.
std::string fMoniCurrrentHostname
The application's monitoring object.
void WriteHistograms()
Open special output file and save eventual performance monitoring histograms into it.
std::map< Subsystem, std::pair< double, double > > fDataSizeMap
Map to store the in and out data amount, key = Subsystem.
std::string sAccEvtTimingFile
Full path to a text file containing the raw Accelerator Event timings.
TH1 * fhRealTimePerTsHist
Plotting time per TS.
TH1 * fhCpuTimePerTsHist
Processing time per TS.
std::map< Subsystem, std::pair< double, double > > fDataSizeMapCurrSec
void Reset()
Clear the output vectors as preparation of the next timeslice. Called via FairSource::Reset()
std::map< Subsystem, TH2 * > fhDigiSpillFilterStopPerDet
Digi time relative to spill start, per detector.
std::string fOutfilename
Name of the performance profiling output file.
std::shared_ptr< CbmStsUnpackConfig > fStsConfig
Configuration of the Sts unpacker. Provides the configured algorithm.
bool bOutputFullTimeSorting
Flag to Enable/disable a full time sorting. If off, time sorting happens per link/FLIM source.
std::map< Subsystem, std::pair< std::string, size_t > > fNameMapPerTs
Map to store a name for the unpackers and the processed amount of digis for a single TS,...
std::shared_ptr< CbmBmonUnpackConfig > fBmonConfig
Configuration of the Bmon unpacker. Provides the configured algorithm.
CbmTsEventHeader * fCbmTsEventHeader
Pointer to the Timeslice start time used to write it to the output tree.
std::vector< AccTimingEvent >::iterator itSpillStart
Current spill start Event.
std::map< Subsystem, TH1 * > fvhOutRatioPerTs
ratio of system data in total input size vs TS in run
void initSpillFilterMonitoring(Subsystem subsystem, std::string name)
Init the Spill filter monitoring histograms for a given system.
void InitSpillFilter()
Digi time relative to spill stop, per detector.
std::shared_ptr< CbmTrdUnpackFaspConfig > fTrd2DConfig
Configuration of the Trd unpacker. Provides the configured algorithm.
bool fPubMoniProcTime
Flag if perf data should be published to moni DB using data time (false) or processing time (true).
TH1 * fhDigiSpillStopDist
Digi time relative to spill start.
std::map< Subsystem, std::pair< double, double > > fTimeMap
Map to store the cpu and wall time, key = Subsystem.
fles::Subsystem Subsystem
bool bMonitoringOnly
Flag to Enable/disable the output completely.
std::map< Subsystem, TH1 * > fhDigiSpillStartDistPerDet
Digi time relative to spill stop.
std::map< Subsystem, TH1 * > fvhInpRatioPerTs
Plotting time per TS.
void initPerformanceMaps(Subsystem subsystem, std::string name)
Init the performance profiling maps for a given unpacker.
std::shared_ptr< CbmTofUnpackConfig > fTofConfig
Configuration of the Tof unpacker. Provides the configured algorithm.
~CbmRecoUnpack()
Destructor.
std::map< Subsystem, std::pair< double, double > > fDataSizeMapPerTs
Map to store the in and out data amount for a single TS, key = Subsystem.
void performanceProfiling()
Run the performance profiling based on the fTimeMap and fDataSizeMap members.
uint32_t uSpillIndex
Index of the current spill in current run.
bool fDoDebugPrints
Flag if extended debug output is to be printed or not.
std::vector< AccTimingEvent > vAccEvtsSpillStart
Storage of spill start accelerator events (Either KickerStart or ExtractionStartSlow)
std::map< Subsystem, std::pair< double, double > > fTimeMapPerTs
Map to store the cpu and wall time for a single TS, key = Subsystem.
bool bSpillFilterMoniFindPeak
Flag to Enable/disable monitoring histos with long range for digi filtering relative to spill start e...
TH2 * fhDigiSpillFilterStart
Digi time relative to spill stop.
TH1 * fhRealTimePerTs
Processing time per TS.
void Unpack(std::unique_ptr< fles::Timeslice > ts)
Trigger the unpacking procedure.
TH1 * fhUnpackingRatioPerTs
ratio of selected digi vs TS in run
std::shared_ptr< CbmMuchUnpackConfig > fMuchConfig
Current time slice.
std::shared_ptr< CbmTrdUnpackConfig > fTrd1DConfig
Configuration of the Trd unpacker. Provides the configured algorithm.
bool fDoPerfProfPerTs
Flag if performance profiling per TS should be activated or not.
std::map< Subsystem, TH1 * > fhDigiSpillStopDistPerDet
Digi time relative to spill start, per detector.
void performanceProfilingPerTs()
Run the performance profiling for a single TS based on the fTimeMapPerTs and fDataSizeMapPerTs member...
bool bSpillFilter
Flag to Enable/disable digi filtering relative to spill start event.
TStopwatch * fTimerTs
std::chrono::system_clock::time_point fMonitorSecCurrentTs
std::shared_ptr< CbmRichUnpackConfig > fRichConfig
Configuration of the Rich unpacker. Provides the configured algorithm.
void RegisterOutputs(FairRootManager *ioman, std::shared_ptr< TConfig > config)
Bool_t Init()
Initialisation.
std::vector< AccTimingEvent >::iterator itSpillStop
Current spill stop Event.
std::map< Subsystem, std::pair< std::string, size_t > > fNameMap
Map to store a name for the unpackers and the processed amount of digis, key = Subsystem.
std::shared_ptr< CbmPsdUnpackConfig > fPsdConfig
Configuration of the Psd unpacker. Provides the configured algorithm.
std::enable_if< std::is_same< TVecobj, std::nullptr_t >::value==true, void >::type timesort(std::vector< TVecobj > *)
Sort a vector timewise vector type has to provide GetTime()
std::enable_if< std::is_same< TVecobj, std::nullptr_t >::value==true, void >::type SpillFilter(uint64_t ulTsStartNs, const Subsystem subsystem, std::vector< TVecobj > *)
Filter a vector timewise relative to spill start. Vector type has to provide GetTime()
bool fDoPerfProf
Flag if performance profiling should be activated or not.
std::vector< AccTimingEvent > vAccEvtsSpillEnd
Storage of spill end accelerator events (ExtractionEnd or ExtractionSlowStop)
Bookkeeping of time-slice content.
std::chrono::time_point< std::chrono::system_clock > sctp