317 {
318 using namespace asg::msgUserCode;
319
323
325 if (!myTool)
326 throw std::runtime_error ("tool is not a ColumnarTool<ColumnarModeXAODArray>");
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 {
340 throw std::runtime_error (
"unexpected type for offset column: " + name +
" " +
data.info.type->name());
342 {
343 data.reader = std::make_shared<TestUtils::ColumnDataXAEventInfo> (
data.info);
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 {
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");
413
416 throw std::runtime_error ("ColumnarPhysLiteTest: numberOfEvents == 0");
417 }
419
420
421
422
423
424
425 const auto startTime = std::chrono::high_resolution_clock::now();
427 {
428 benchmarkEmpty.startTimer ();
429 benchmarkEmpty.stopTimer ();
430
431 benchmarkGetEntry.startTimer ();
433 benchmarkGetEntry.stopTimer ();
434
435 ColumnVectorData columnData (&columnHeader);
436 for (
auto& [name,
data] : requestedColumns)
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 ();
448 {
449 benchmarkCall2.startTimer ();
450 columnData.callNoCheck (*myTool);
451 benchmarkCall2.stopTimer ();
452 }
453
454 benchmarkCallClear.startTimer ();
456 benchmarkCallClear.stopTimer ();
457 benchmarkEmptyClear.startTimer ();
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" << 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
472 {
473 std::vector<BranchPerfData> columnPerfData;
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);
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
519 {
520 std::vector<ToolPerfData> toolPerfData;
521 toolPerfData.emplace_back();
522 toolPerfData.back().name = testDefinition.
name;
523 toolPerfData.back().timeCall = benchmarkCall.getEntryTime(emptyTime);
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);
539 std::cout << std::format(
"{:>9.0f} |",
data.timeCall.value());
540 else
541 std::cout << " |";
543 std::cout << std::format(
"{:>10.0f} |",
data.timeCall2.value());
544 else
545 std::cout << " |";
547 std::cout << std::format(
"{:>10.1f}",
data.timeCheck.value());
548 std::cout << std::endl;
549 }
550 }
551 }
char data[hepevt_bytes_allocation_ATLAS]
the header information for the entire columnar data vector
this is a simple benchmarking helper class wrapping timers from std::chrono
Tool for accessing xAOD files outside of Athena.
A relatively simple transient store for objects created in analysis.
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
std::chrono::seconds targetTime