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...
class  ColumnarTestToolHandle
 a handle to a columnar tool for running tests More...
struct  ColumnMapType
struct  UserConfiguration
 a struct holding user configuration for the PHYSLITE tests More...
struct  TestDefinition
 the general configuration for a single test More...
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  BranchPerfData
 the performance data for reading a single branch/column 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  RNTupleBackend
class  BranchReader
class  BranchReaderArray
class  LinkColumnVector
class  RNTFieldReader
class  IColumnData
struct  ColumnDataEventCount
struct  ColumnDataScalar
struct  ColumnDataVector
struct  ColumnDataOutVector
struct  ColumnDataVectorVector
struct  ColumnDataVectorVectorVector
struct  ColumnDataMetNames
struct  ColumnDataOutputMet
struct  ColumnDataSamplingPattern

Typedefs

using Backend = std::variant<TTree*, RNTupleBackend*>

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

Typedef Documentation

◆ Backend

using columnar::TestUtils::Backend = std::variant<TTree*, RNTupleBackend*>

Definition at line 82 of file ColumnarPhysliteTest.cxx.

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 317 of file PhysliteTestXaodArray.cxx.

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

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