ATLAS Offline Software
Loading...
Searching...
No Matches
columnar::TestUtils Namespace Reference

Classes

class  Benchmark
 this is a simple benchmarking helper class wrapping timers from std::chrono More...
struct  BranchPerfData
 the performance data for reading a single branch/column More...
class  BranchReader
class  BranchReaderArray
class  ColumnarTestToolHandle
 a handle to a columnar tool for running tests More...
struct  ColumnDataEventCount
struct  ColumnDataMetNames
struct  ColumnDataOutputMet
struct  ColumnDataOutVector
struct  ColumnDataSamplingPattern
struct  ColumnDataScalar
struct  ColumnDataVector
struct  ColumnDataVectorVector
struct  ColumnDataVectorVectorVector
struct  ColumnMapType
class  IColumnData
class  IXAODToolCaller
 a wrapper around a CP tool in xAOD mdoe to call it in the PHYSLITE test More...
class  ManualColumnData
 a class that holds manually specified column data More...
struct  TestDefinition
 the general configuration for a single test More...
struct  ToolPerfData
 the performance data for running a single tool More...
class  ToolWrapperData
 a class that holds a reference to a ToolColumnVectorMap and a ColumnVectorData More...
struct  UserConfiguration
 a struct holding user configuration for the PHYSLITE tests More...

Functions

void checkExpectation (const std::string &columnName, const std::type_info &outputType, std::size_t outputSize, const void *outputData, const std::type_info &expectationType, std::size_t expectationSize, const void *expectationData)
void printExpectedOutput (const std::string &columnName, const std::type_info &outputType, std::size_t outputSize, const void *outputData)
void runXaodTest (const UserConfiguration &userConfiguration, std::span< const TestDefinition > testDefinitions, TFile *file)
void runXaodArrayTest (const UserConfiguration &userConfiguration, const TestDefinition &testDefinition, TFile *file)

Variables

const std::unordered_map< std::string, SG::sgkey_tknownKeys

Function Documentation

◆ checkExpectation()

void columnar::TestUtils::checkExpectation ( const std::string & columnName,
const std::type_info & outputType,
std::size_t outputSize,
const void * outputData,
const std::type_info & expectationType,
std::size_t expectationSize,
const void * expectationData )

Definition at line 46 of file ExpectationCompare.cxx.

47 {
48 SCOPED_TRACE (columnName);
49 ASSERT_EQ (outputType, expectationType);
50 if (outputType == typeid(float))
51 checkExpectationTyped (columnName, std::span<const float> (static_cast<const float*> (outputData), outputSize), std::span<const float> (static_cast<const float*> (expectationData), expectationSize));
52 else if (outputType == typeid(char))
53 checkExpectationTyped (columnName, std::span<const char> (static_cast<const char*> (outputData), outputSize), std::span<const char> (static_cast<const char*> (expectationData), expectationSize));
54 else if (outputType == typeid(int))
55 checkExpectationTyped (columnName, std::span<const int> (static_cast<const int*> (outputData), outputSize), std::span<const int> (static_cast<const int*> (expectationData), expectationSize));
56 else if (outputType == typeid(std::uint8_t))
57 checkExpectationTyped (columnName, std::span<const std::uint8_t> (static_cast<const std::uint8_t*> (outputData), outputSize), std::span<const std::uint8_t> (static_cast<const std::uint8_t*> (expectationData), expectationSize));
58 else if (outputType == typeid(std::uint16_t))
59 checkExpectationTyped (columnName, std::span<const std::uint16_t> (static_cast<const std::uint16_t*> (outputData), outputSize), std::span<const std::uint16_t> (static_cast<const std::uint16_t*> (expectationData), expectationSize));
60 else if (outputType == typeid(std::uint32_t))
61 checkExpectationTyped (columnName, std::span<const std::uint32_t> (static_cast<const std::uint32_t*> (outputData), outputSize), std::span<const std::uint32_t> (static_cast<const std::uint32_t*> (expectationData), expectationSize));
62 else if (outputType == typeid(std::uint64_t))
63 checkExpectationTyped (columnName, std::span<const std::uint64_t> (static_cast<const std::uint64_t*> (outputData), outputSize), std::span<const std::uint64_t> (static_cast<const std::uint64_t*> (expectationData), expectationSize));
64 else if (outputType == typeid(std::size_t))
65 checkExpectationTyped (columnName, std::span<const std::size_t> (static_cast<const std::size_t*> (outputData), outputSize), std::span<const std::size_t> (static_cast<const std::size_t*> (expectationData), expectationSize));
66 else
67 throw std::logic_error ("received unsupported type " + boost::core::demangle(outputType.name()) + " for column compare, cast value or extend test handler to support it");
68 }

◆ printExpectedOutput()

void columnar::TestUtils::printExpectedOutput ( const std::string & columnName,
const std::type_info & outputType,
std::size_t outputSize,
const void * outputData )

Definition at line 93 of file ExpectationCompare.cxx.

94 {
95 if (outputType == typeid(float))
96 printExpectedOutputTyped (columnName, std::span<const float> (static_cast<const float*> (outputData), outputSize));
97 else if (outputType == typeid(char))
98 printExpectedOutputTyped (columnName, std::span<const char> (static_cast<const char*> (outputData), outputSize));
99 else if (outputType == typeid(int))
100 printExpectedOutputTyped (columnName, std::span<const int> (static_cast<const int*> (outputData), outputSize));
101 else if (outputType == typeid(std::uint8_t))
102 printExpectedOutputTyped (columnName, std::span<const std::uint8_t> (static_cast<const std::uint8_t*> (outputData), outputSize));
103 else if (outputType == typeid(std::uint16_t))
104 printExpectedOutputTyped (columnName, std::span<const std::uint16_t> (static_cast<const std::uint16_t*> (outputData), outputSize));
105 else if (outputType == typeid(std::uint32_t))
106 printExpectedOutputTyped (columnName, std::span<const std::uint32_t> (static_cast<const std::uint32_t*> (outputData), outputSize));
107 else if (outputType == typeid(std::uint64_t))
108 printExpectedOutputTyped (columnName, std::span<const std::uint64_t> (static_cast<const std::uint64_t*> (outputData), outputSize));
109 else if (outputType == typeid(std::size_t))
110 printExpectedOutputTyped (columnName, std::span<const std::size_t> (static_cast<const std::size_t*> (outputData), outputSize));
111 else
112 throw std::logic_error ("received unsupported type " + boost::core::demangle(outputType.name()) + " for column printout, cast value or extend test handler to support it");
113 }

◆ runXaodArrayTest()

void columnar::TestUtils::runXaodArrayTest ( const UserConfiguration & userConfiguration,
const TestDefinition & testDefinition,
TFile * file )

Definition at line 316 of file PhysliteTestXaodArray.cxx.

317 {
318 using namespace asg::msgUserCode;
319
320 xAOD::TEvent event;
321 xAOD::TStore store;
322 ANA_CHECK_THROW (event.readFrom (file));
323
324 auto *myTool = dynamic_cast<ColumnarTool<ColumnarModeXAODArray>*>(testDefinition.tool);
325 if (!myTool)
326 throw std::runtime_error ("tool is not a ColumnarTool<ColumnarModeXAODArray>");
327 if (!testDefinition.containerRenames.empty())
328 renameContainers (*myTool, testDefinition.containerRenames);
329 ColumnVectorHeader columnHeader;
330 ToolColumnVectorMap toolWrapper (columnHeader, *myTool);
331
332 std::unordered_map<std::string,TestUtils::ColumnDataXA> requestedColumns;
333 for (auto& column : myTool->getColumnInfo())
334 requestedColumns[column.name].info = std::move (column);
335 for (auto& [name, data] : requestedColumns)
336 {
337 if (data.info.isOffset)
338 {
339 if (*data.info.type != typeid(ColumnarOffsetType))
340 throw std::runtime_error ("unexpected type for offset column: " + name + " " + data.info.type->name());
341 if (name == numberOfEventsName)
342 {
343 data.reader = std::make_shared<TestUtils::ColumnDataXAEventInfo> (data.info);
344 } else if (data.info.offsetName == numberOfEventsName)
345 {
346 if (name == "AnalysisMuons")
347 data.reader = std::make_shared<TestUtils::ColumnDataXARetrieve<xAOD::MuonContainer>> (data.info, userConfiguration);
348 else if (name == "AnalysisElectrons")
349 data.reader = std::make_shared<TestUtils::ColumnDataXARetrieve<xAOD::ElectronContainer>> (data.info, userConfiguration);
350 else if (name == "AnalysisPhotons")
351 data.reader = std::make_shared<TestUtils::ColumnDataXARetrieve<xAOD::PhotonContainer>> (data.info, userConfiguration);
352 else if (name == "egammaClusters")
353 data.reader = std::make_shared<TestUtils::ColumnDataXARetrieve<xAOD::CaloClusterContainer>> (data.info, userConfiguration);
354 else if (name == "GSFTrackParticles")
355 data.reader = std::make_shared<TestUtils::ColumnDataXARetrieve<xAOD::TrackParticleContainer>> (data.info, userConfiguration);
356 else if (name == "GSFConversionVertices")
357 data.reader = std::make_shared<TestUtils::ColumnDataXARetrieve<xAOD::VertexContainer>> (data.info, userConfiguration);
358 }
359 } else
360 {
361 if (*data.info.type == typeid(float))
362 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<float>> (data.info, userConfiguration);
363 else if (*data.info.type == typeid(double))
364 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<double>> (data.info, userConfiguration);
365 else if (*data.info.type == typeid(char))
366 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<char>> (data.info, userConfiguration);
367 else if (*data.info.type == typeid(std::uint8_t))
368 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<std::uint8_t>> (data.info, userConfiguration);
369 else if (*data.info.type == typeid(std::uint16_t))
370 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<std::uint16_t>> (data.info, userConfiguration);
371 else if (*data.info.type == typeid(std::uint32_t))
372 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<std::uint32_t>> (data.info, userConfiguration);
373 else if (*data.info.type == typeid(std::uint64_t))
374 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<std::uint64_t>> (data.info, userConfiguration);
375 else if (*data.info.type == typeid(std::vector<float>))
376 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<std::vector<float>>> (data.info, userConfiguration);
377 else if (*data.info.type == typeid(std::vector<ElementLink<xAOD::CaloClusterContainer>>))
378 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<std::vector<ElementLink<xAOD::CaloClusterContainer>>>> (data.info, userConfiguration);
379 else if (*data.info.type == typeid(std::vector<ElementLink<xAOD::TrackParticleContainer>>))
380 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<std::vector<ElementLink<xAOD::TrackParticleContainer>>>> (data.info, userConfiguration);
381 else if (*data.info.type == typeid(std::vector<ElementLink<xAOD::VertexContainer>>))
382 data.reader = std::make_shared<TestUtils::ColumnDataXAAccessor<std::vector<ElementLink<xAOD::VertexContainer>>>> (data.info, userConfiguration);
383 }
384 }
385
386 bool allColumnsHandled = true;
387 for (auto& [name, data] : requestedColumns)
388 {
389 if (!data.reader)
390 {
391 allColumnsHandled = false;
392 std::cout << "WARNING: no handling for requested column: name=" << name << " offset=" << data.info.offsetName << " type=" << boost::core::demangle(data.info.type->name()) << std::endl;
393 }
394 }
395 if (!allColumnsHandled)
396 {
397 ADD_FAILURE() << "not all requested columns could be handled";
398 return;
399 }
400
401 for (auto& [name, data]: requestedColumns)
402 {
403 data.reader->connect (data, requestedColumns);
404 }
405
406 Benchmark benchmarkEmptyClear (testDefinition.name + " empty clear");
407 Benchmark benchmarkCallClear (testDefinition.name + " call clear");
408 Benchmark benchmarkGetEntry (testDefinition.name + " getEntry");
409 Benchmark benchmarkCheck (testDefinition.name + " check");
410 Benchmark benchmarkCall2 (testDefinition.name + " call2");
411 Benchmark benchmarkCall (testDefinition.name + " call");
412 Benchmark benchmarkEmpty ("empty");
413
414 const auto numberOfEvents = event.getEntries();
415 if (numberOfEvents == 0){
416 throw std::runtime_error ("ColumnarPhysLiteTest: numberOfEvents == 0");
417 }
418 Long64_t entry = 0;
419
420 // Instead of running for a fixed number of events, we run for a
421 // fixed amount of time. That is because individual tools can
422 // vary wildly in how long they take to run, and we mostly want to
423 // make sure that we ran the tool enough to get a precise
424 // performance estimate.
425 const auto startTime = std::chrono::high_resolution_clock::now();
426 for (; (std::chrono::high_resolution_clock::now() - startTime) < userConfiguration.targetTime; ++entry)
427 {
428 benchmarkEmpty.startTimer ();
429 benchmarkEmpty.stopTimer ();
430
431 benchmarkGetEntry.startTimer ();
432 event.getEntry (entry % numberOfEvents);
433 benchmarkGetEntry.stopTimer ();
434
435 ColumnVectorData columnData (&columnHeader);
436 for (auto& [name, data] : requestedColumns)
437 ASSERT_SUCCESS (data.reader->retrieveContainer (event, store, columnData));
438 for (auto& [name, data] : requestedColumns)
439 data.reader->retrieveAuxData (columnData);
440
441 benchmarkCheck.startTimer ();
442 columnData.checkData ();
443 benchmarkCheck.stopTimer ();
444 benchmarkCall.startTimer ();
445 columnData.callNoCheck (*myTool);
446 benchmarkCall.stopTimer ();
447 if (userConfiguration.runToolTwice)
448 {
449 benchmarkCall2.startTimer ();
450 columnData.callNoCheck (*myTool);
451 benchmarkCall2.stopTimer ();
452 }
453
454 benchmarkCallClear.startTimer ();
455 store.clear ();
456 benchmarkCallClear.stopTimer ();
457 benchmarkEmptyClear.startTimer ();
458 store.clear ();
459 benchmarkEmptyClear.stopTimer ();
460 }
461 std::cout << "Total entries read: " << entry << std::endl;
462 const float emptyTime = benchmarkEmpty.getEntryTime(0).value();
463 std::cout << "Empty benchmark time: " << emptyTime << "ns (tick=" << Benchmark::getTickDuration() << "ns)" << std::endl;
464 benchmarkEmpty.setSilence();
465 std::cout << "Average getEntry time: " << benchmarkGetEntry.getEntryTime(emptyTime).value() << "ns" << std::endl;
466 benchmarkGetEntry.setSilence();
467 std::cout << "Average clear time: " << benchmarkCallClear.getEntryTime(emptyTime).value() << "ns" << " (empty=" << benchmarkEmptyClear.getEntryTime(emptyTime).value() << "ns)" << std::endl;
468 benchmarkCallClear.setSilence();
469 benchmarkEmptyClear.setSilence();
470
471 // Column performance table
472 {
473 std::vector<BranchPerfData> columnPerfData;
475 summary.name = "total";
476 summary.timeRead = 0;
477 summary.timeReadAgain = 0;
478 summary.timeShallowCopy = 0;
479 summary.timeShallowRegister = 0;
480 for (auto& [name, data] : requestedColumns)
481 {
482 auto perfData = data.reader->getPerfData(emptyTime);
483 if (perfData.timeRead.has_value() || perfData.timeReadAgain.has_value())
484 {
485 columnPerfData.push_back(perfData);
486 summary.timeRead.value() += perfData.timeRead.value_or(0);
487 summary.timeReadAgain.value() += perfData.timeReadAgain.value_or(0);
488 summary.timeShallowCopy.value() += perfData.timeShallowCopy.value_or(0);
489 summary.timeShallowRegister.value() += perfData.timeShallowRegister.value_or(0);
490 }
491 }
492 std::sort(columnPerfData.begin(), columnPerfData.end(), [](const auto& a, const auto& b) { return a.name < b.name; });
493 columnPerfData.push_back(summary);
494
495 const std::size_t nameWidth = std::max_element(columnPerfData.begin(), columnPerfData.end(), [](const auto& a, const auto& b) { return a.name.size() < b.name.size(); })->name.size();
496 std::string header = std::format("{:{}} | 1st(ns) | 2nd(ns) | shallow copy(ns)", "column name", nameWidth);
497 std::cout << "\n" << header << std::endl;
498 std::cout << std::string(header.size(), '-') << std::endl;
499 for (auto& data : columnPerfData)
500 {
501 if (data.name == "total")
502 std::cout << std::string(header.size(), '-') << std::endl;
503 std::cout << std::format("{:{}} |", data.name, nameWidth);
504 if (data.timeRead)
505 std::cout << std::format("{:>8.0f} |", data.timeRead.value());
506 else
507 std::cout << " |";
508 if (data.timeReadAgain)
509 std::cout << std::format("{:>8.1f} |", data.timeReadAgain.value());
510 else
511 std::cout << " |";
512 if (data.timeShallowCopy || data.timeShallowRegister)
513 std::cout << std::format("{:>10.0f} +{:>5.0f}", data.timeShallowCopy.value_or(-1), data.timeShallowRegister .value_or(-1));
514 std::cout << std::endl;
515 }
516 }
517
518 // Tool performance table
519 {
520 std::vector<ToolPerfData> toolPerfData;
521 toolPerfData.emplace_back();
522 toolPerfData.back().name = testDefinition.name;
523 toolPerfData.back().timeCall = benchmarkCall.getEntryTime(emptyTime);
524 if (userConfiguration.runToolTwice)
525 toolPerfData.back().timeCall2 = benchmarkCall2.getEntryTime(emptyTime);
526 toolPerfData.back().timeCheck = benchmarkCheck.getEntryTime(emptyTime);
527 benchmarkCall.setSilence();
528 benchmarkCall2.setSilence();
529 benchmarkCheck.setSilence();
530
531 const std::size_t nameWidth = std::max_element(toolPerfData.begin(), toolPerfData.end(), [](const auto& a, const auto& b) { return a.name.size() < b.name.size(); })->name.size();
532 std::string header = std::format("{:{}} | call(ns) | call2(ns) | check(ns)", "tool name", nameWidth);
533 std::cout << "\n" << header << std::endl;
534 std::cout << std::string(header.size(), '-') << std::endl;
535 for (auto& data : toolPerfData)
536 {
537 std::cout << std::format("{:{}} |", data.name, nameWidth);
538 if (data.timeCall)
539 std::cout << std::format("{:>9.0f} |", data.timeCall.value());
540 else
541 std::cout << " |";
542 if (data.timeCall2)
543 std::cout << std::format("{:>10.0f} |", data.timeCall2.value());
544 else
545 std::cout << " |";
546 if (data.timeCheck)
547 std::cout << std::format("{:>10.1f}", data.timeCheck.value());
548 std::cout << std::endl;
549 }
550 }
551 }
#define ANA_CHECK_THROW(EXP)
check whether the given expression was successful, throwing an exception on failure
int numberOfEvents()
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
static Double_t a
the header information for the entire columnar data vector
the base class for all columnar components
this is a simple benchmarking helper class wrapping timers from std::chrono
Definition Benchmark.h:51
static float getTickDuration()
Definition Benchmark.h:86
a class that interfaces an IColumnarTool to a ColumnVectorHeader
Tool for accessing xAOD files outside of Athena.
A relatively simple transient store for objects created in analysis.
Definition TStore.h:45
TestStore store
Definition TestStore.cxx:23
const std::string numberOfEventsName
the name used for the column containing the number of events
void renameContainers(IColumnarTool &tool, const std::vector< std::pair< std::string, std::string > > &renames)
rename containers in the columnar tool
std::size_t ColumnarOffsetType
the type used for the size and offsets in the columnar data
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
the performance data for reading a single branch/column
std::vector< std::pair< std::string, std::string > > containerRenames
the container name remappings to apply
TFile * file

◆ runXaodTest()

void columnar::TestUtils::runXaodTest ( const UserConfiguration & userConfiguration,
std::span< const TestDefinition > testDefinitions,
TFile * file )

Definition at line 266 of file PhysliteTestXaod.cxx.

267 {
268 using namespace asg::msgUserCode;
269
270 auto eventReader = makeEventReader();
271 ANA_CHECK_THROW(eventReader->readFrom(file));
272
273 std::vector<ToolData> toolDataVec;
274 for (const auto& testDefinition : testDefinitions)
275 {
276 if (testDefinition.xAODToolCaller != nullptr)
277 {
278 ToolData toolData;
279 toolData.name = testDefinition.name;
280 toolData.xAODToolCaller = testDefinition.xAODToolCaller;
281 toolData.noRepeatCall = testDefinition.noRepeatCall;
282 toolDataVec.push_back(std::move(toolData));
283 }
284 }
285
286 IXAODToolCaller::EventStoreType* evtStore = nullptr;
287 if (!testDefinitions.empty() && testDefinitions[0].tool)
288 evtStore = &*testDefinitions[0].tool->evtStore();
289
290 Benchmark benchmarkEmpty;
291
292 const std::uint64_t numberOfEvents = eventReader->getEntries();
293 if (numberOfEvents == 0){
294 throw std::runtime_error ("ColumnarPhysLiteTest: numberOfEvents == 0");
295 }
296 std::uint64_t entry = 0;
297
298 // Instead of running for a fixed number of events, we run for a
299 // fixed amount of time. That is because individual tools can
300 // vary wildly in how long they take to run, and we mostly want to
301 // make sure that we ran the tool enough to get a precise
302 // performance estimate.
303 const auto startTime = std::chrono::high_resolution_clock::now();
304 for (; (std::chrono::high_resolution_clock::now() - startTime) < userConfiguration.targetTime; ++entry)
305 {
306 benchmarkEmpty.startTimer();
307 benchmarkEmpty.stopTimer();
308 ANA_CHECK_THROW(eventReader->getEntry(entry % numberOfEvents));
309 if (eventReader->hasClearStore())
310 {
311 static const std::string prepPostfix = "Prep";
312 for (auto& toolData : toolDataVec)
313 ASSERT_SUCCESS (toolData.retrieve (0, *evtStore));
314 for (auto& toolData : toolDataVec)
315 ASSERT_SUCCESS (toolData.copyRecord (0, *evtStore, prepPostfix));
316 for (auto& toolData : toolDataVec)
317 ASSERT_SUCCESS (toolData.call (0));
318 for (auto& toolData : toolDataVec)
319 toolData.clear (0);
320 eventReader->clearStore();
321 }
322 static const std::string callPostfix = "Call";
323 for (auto& toolData : toolDataVec)
324 ASSERT_SUCCESS (toolData.retrieve (1, *evtStore));
325 for (auto& toolData : toolDataVec)
326 ASSERT_SUCCESS (toolData.copyRecord (1, *evtStore, callPostfix));
327 for (auto& toolData : toolDataVec)
328 {
329 ASSERT_SUCCESS (toolData.call (1));
330 // a second call, immediately after, to have the tool in
331 // instruction cache and simulate it being run on multi-event
332 // batches. this is a bit too good, as it will run on exactly
333 // the same event, instead of different events as would happen
334 // in a real multi-event batch.
335 if (userConfiguration.runToolTwice && !toolData.noRepeatCall)
336 {
337 ASSERT_SUCCESS (toolData.call (2));
338 }
339 }
340 for (auto& toolData : toolDataVec)
341 toolData.clear (1);
342 if (eventReader->hasClearStore())
343 eventReader->clearStore();
344 }
345 std::cout << "Total entries read: " << entry << std::endl;
346 const float emptyTime = benchmarkEmpty.getEntryTime(0).value();
347 std::cout << "Empty benchmark time: " << emptyTime << "ns (tick=" << Benchmark::getTickDuration() << "ns)" << std::endl;
348 eventReader->printBenchmarkTable(emptyTime);
349
350 // Fill vector of ToolPerfData pairs from benchmarks
351 std::vector<std::pair<ToolPerfData, ToolPerfData>> toolPerfData;
352 for (auto& toolData : toolDataVec)
353 {
354 ToolPerfData prepPerfData;
355 prepPerfData.name = toolData.name;
356 if (eventReader->hasClearStore()) {
357 prepPerfData.timeRetrieve = toolData.benchmarkRetrieve[0].getEntryTime(emptyTime);
358 prepPerfData.timeCopyRecord = toolData.benchmarkCopyRecord[0].getEntryTime(emptyTime);
359 prepPerfData.timeCall = toolData.benchmarkCall[0].getEntryTime(emptyTime);
360 prepPerfData.timeClear = toolData.benchmarkClear[0].getEntryTime(emptyTime);
361 toolData.benchmarkRetrieve[0].setSilence();
362 toolData.benchmarkCopyRecord[0].setSilence();
363 toolData.benchmarkCall[0].setSilence();
364 toolData.benchmarkClear[0].setSilence();
365 }
366
367 ToolPerfData callPerfData;
368 callPerfData.name = toolData.name;
369 callPerfData.timeRetrieve = toolData.benchmarkRetrieve[1].getEntryTime(emptyTime);
370 callPerfData.timeCopyRecord = toolData.benchmarkCopyRecord[1].getEntryTime(emptyTime);
371 callPerfData.timeCall = toolData.benchmarkCall[1].getEntryTime(emptyTime);
372 callPerfData.timeClear = toolData.benchmarkClear[1].getEntryTime(emptyTime);
373 if (userConfiguration.runToolTwice) {
374 callPerfData.timeCall2 = toolData.benchmarkCall[2].getEntryTime(emptyTime);
375 toolData.benchmarkCall[2].setSilence();
376 }
377 toolData.benchmarkRetrieve[1].setSilence();
378 toolData.benchmarkCopyRecord[1].setSilence();
379 toolData.benchmarkCall[1].setSilence();
380 toolData.benchmarkClear[1].setSilence();
381
382 toolPerfData.emplace_back(std::move(prepPerfData), std::move(callPerfData));
383 }
384
385 // Helper lambda for printing optional time values
386 auto printOptionalTime = [](std::optional<float> time, int width, bool trailingBar = true) {
387 if (time)
388 std::cout << std::format("{:>{}.0f}", time.value(), width);
389 else
390 std::cout << std::format("{:>{}}", "", width);
391 if (trailingBar)
392 std::cout << " |";
393 };
394
395 // Calculate name width from all entries
396 std::size_t nameWidth = std::string_view("tool name").size();
397 for (const auto& [prep, call] : toolPerfData)
398 nameWidth = std::max(nameWidth, prep.name.size());
399
400 // Print tool performance table with grouped columns
401 std::string groupHeader = std::format("{:{}} |{:^42}|{:^52}",
402 "", nameWidth, "prep", "call");
403 std::string colHeader = std::format("{:{}} | retr(ns) | copy(ns) | call(ns) | clr(ns) | retr(ns) | copy(ns) | call(ns) | 2nd(ns) | clr(ns)",
404 "tool name", nameWidth);
405
406 std::cout << "\ntool benchmarks:" << std::endl;
407 std::cout << groupHeader << std::endl;
408 std::cout << colHeader << std::endl;
409 std::cout << std::string(colHeader.size(), '-') << std::endl;
410
411 // Print data rows
412 for (const auto& [prep, call] : toolPerfData)
413 {
414 std::cout << std::format("{:{}} |", prep.name, nameWidth);
415 printOptionalTime(prep.timeRetrieve, 9);
416 printOptionalTime(prep.timeCopyRecord, 9);
417 printOptionalTime(prep.timeCall, 9);
418 printOptionalTime(prep.timeClear, 8);
419 printOptionalTime(call.timeRetrieve, 9);
420 printOptionalTime(call.timeCopyRecord, 9);
421 printOptionalTime(call.timeCall, 9);
422 printOptionalTime(call.timeCall2, 8);
423 printOptionalTime(call.timeClear, 8, false);
424 std::cout << std::endl;
425 }
426
427 // Print total line only when there are multiple tools
428 if (toolPerfData.size() > 1)
429 {
430 std::optional<float> totalPrepRetrieve, totalPrepCopyRecord, totalPrepCall, totalPrepClear;
431 std::optional<float> totalCallRetrieve, totalCallCopyRecord, totalCallCall, totalCallClear, totalRepeat;
432 for (const auto& [prep, call] : toolPerfData)
433 {
434 if (prep.timeRetrieve)
435 totalPrepRetrieve = totalPrepRetrieve.value_or(0) + prep.timeRetrieve.value();
436 if (prep.timeCopyRecord)
437 totalPrepCopyRecord = totalPrepCopyRecord.value_or(0) + prep.timeCopyRecord.value();
438 if (prep.timeCall)
439 totalPrepCall = totalPrepCall.value_or(0) + prep.timeCall.value();
440 if (prep.timeClear)
441 totalPrepClear = totalPrepClear.value_or(0) + prep.timeClear.value();
442 if (call.timeRetrieve)
443 totalCallRetrieve = totalCallRetrieve.value_or(0) + call.timeRetrieve.value();
444 if (call.timeCopyRecord)
445 totalCallCopyRecord = totalCallCopyRecord.value_or(0) + call.timeCopyRecord.value();
446 if (call.timeCall)
447 totalCallCall = totalCallCall.value_or(0) + call.timeCall.value();
448 if (call.timeClear)
449 totalCallClear = totalCallClear.value_or(0) + call.timeClear.value();
450 if (call.timeCall2)
451 totalRepeat = totalRepeat.value_or(0) + call.timeCall2.value();
452 }
453
454 std::cout << std::string(colHeader.size(), '-') << std::endl;
455 std::cout << std::format("{:{}} |", "total", nameWidth);
456 printOptionalTime(totalPrepRetrieve, 9);
457 printOptionalTime(totalPrepCopyRecord, 9);
458 printOptionalTime(totalPrepCall, 9);
459 printOptionalTime(totalPrepClear, 8);
460 printOptionalTime(totalCallRetrieve, 9);
461 printOptionalTime(totalCallCopyRecord, 9);
462 printOptionalTime(totalCallCall, 9);
463 printOptionalTime(totalRepeat, 8);
464 printOptionalTime(totalCallClear, 8, false);
465 std::cout << std::endl;
466 }
467 }
const double width
std::optional< float > getEntryTime(float emptyTime) const
Definition Benchmark.h:74
std::decay_t< decltype(*std::declval< asg::AsgTool >().evtStore())> EventStoreType
the type used for the event store
time(flags, cells_name, *args, **kw)
call(args, bufsize=0, executable=None, stdin=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0, message="", logger=msg, loglevel=None, timeout=None, retry=2, timefactor=1.5, sleeptime=10)
Definition trfUtils.py:155
the performance data for running a single tool

Variable Documentation

◆ knownKeys

const std::unordered_map< std::string, SG::sgkey_t > columnar::TestUtils::knownKeys
Initial value:
=
{
{"AnalysisMuons", 0x3a6b126f},
{"AnalysisElectrons", 0x3902fec0},
{"AnalysisPhotons", 0x35d1472f},
{"AnalysisJets", 0x1afd1919},
{"egammaClusters", 0x15788d1f},
{"GSFConversionVertices", 0x1f3e85c9},
{"InDetTrackParticles", 0x1d3890db},
{"CombinedMuonTrackParticles", 0x340d9196},
{"ExtrapolatedMuonTrackParticles", 0x14e35e9f},
{"GSFTrackParticles", 0x2e42db0b},
{"InDetForwardTrackParticles", 0x143c6846},
{"MuonSpectrometerTrackParticles", 0x3993c8f3},
}

Definition at line 24 of file PhysliteTest.cxx.

25 {
26 {"AnalysisMuons", 0x3a6b126f},
27 {"AnalysisElectrons", 0x3902fec0},
28 {"AnalysisPhotons", 0x35d1472f},
29 {"AnalysisJets", 0x1afd1919},
30 {"egammaClusters", 0x15788d1f},
31 {"GSFConversionVertices", 0x1f3e85c9},
32 {"InDetTrackParticles", 0x1d3890db},
33 {"CombinedMuonTrackParticles", 0x340d9196},
34 {"ExtrapolatedMuonTrackParticles", 0x14e35e9f},
35 {"GSFTrackParticles", 0x2e42db0b},
36 {"InDetForwardTrackParticles", 0x143c6846},
37 {"MuonSpectrometerTrackParticles", 0x3993c8f3},
38 };