40#ifndef XAOD_STANDALONE
48#include <boost/core/demangle.hpp>
56#include <gtest/gtest.h>
73 static const std::unordered_map<std::string,SG::sgkey_t>
knownKeys =
75 {
"AnalysisMuons", 0x3a6b126f},
76 {
"AnalysisElectrons", 0x3902fec0},
77 {
"AnalysisPhotons", 0x35d1472f},
78 {
"AnalysisJets", 0x1afd1919},
79 {
"egammaClusters", 0x15788d1f},
80 {
"GSFConversionVertices", 0x1f3e85c9},
81 {
"InDetTrackParticles", 0x1d3890db},
82 {
"CombinedMuonTrackParticles", 0x340d9196},
83 {
"ExtrapolatedMuonTrackParticles", 0x14e35e9f},
84 {
"GSFTrackParticles", 0x2e42db0b},
85 {
"InDetForwardTrackParticles", 0x143c6846},
86 {
"MuonSpectrometerTrackParticles", 0x3993c8f3},
130 else if (
columnName.find (
".") != std::string::npos)
131 throw std::runtime_error (
"branch name does not contain AuxDyn or Aux: " +
m_branchName);
144 throw std::runtime_error (
"branch name does not contain AuxDyn or Aux: " +
m_branchName);
151 throw std::runtime_error (
"failed to get branch: " +
m_branchName);
162 throw std::runtime_error (
"branch not connected: " +
m_branchName);
163 if (
m_branch->GetEntry (entry) <= 0)
164 throw std::runtime_error (
"failed to get entry " + std::to_string (entry) +
" for branch: " +
m_branchName);
166 throw std::runtime_error (
"got nullptr reading data for branch: " +
m_branchName);
179 return static_cast<float>(
m_branch->GetZipBytes()) /
m_branch->GetEntries();
186 return static_cast<float>(
m_branch->GetTotBytes()) /
m_branch->GetEntries();
195 return m_branch->GetListOfBaskets()->GetSize();
222 else if (
columnName.find (
".") != std::string::npos)
223 throw std::runtime_error (
"branch name does not contain AuxDyn or Aux: " +
m_branchName);
236 throw std::runtime_error (
"branch name does not contain AuxDyn or Aux: " +
m_branchName);
243 throw std::runtime_error (
"failed to get branch: " +
m_branchName);
249 std::span<const T>
getEntry (Long64_t entry, std::size_t size)
252 throw std::runtime_error (
"branch not connected: " +
m_branchName);
258 if (size > 0 &&
m_branch->GetEntry (entry) <= 0)
259 throw std::runtime_error (
"failed to get entry " + std::to_string (entry) +
" for branch: " +
m_branchName);
260 return std::span<const T>(
m_dataVec.data(), size);
267 return static_cast<float>(
m_branch->GetZipBytes()) /
m_branch->GetEntries();
274 return static_cast<float>(
m_branch->GetTotBytes()) /
m_branch->GetEntries();
283 return m_branch->GetListOfBaskets()->GetSize();
317 std::array<ColumnarOffsetType, 2>
data = {0, 0};
324 virtual bool connect (TTree * , std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& , std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
355 result.name =
"EventCount(auto)";
378 virtual bool connect (TTree *
tree, std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& , std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
380 auto iter = requestedColumns.find (
outputColumns.at(0).name);
381 if (iter == requestedColumns.end())
384 requestedColumns.erase (iter);
402 outData.push_back (branchData);
438 std::vector<ColumnarOffsetType>
offsets = {0};
451 virtual bool connect (TTree *
tree, std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& offsetColumns, std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
453 auto iter = requestedColumns.find (
outputColumns.at(0).name);
454 if (iter == requestedColumns.end())
461 throw std::runtime_error (
"offset name mismatch: " + iter->second.offsetName +
" != " +
outputColumns.at(1).name);
463 requestedColumns.erase (iter);
465 if (
auto offsetIter = offsetColumns.find (
outputColumns.at(1).name); offsetIter != offsetColumns.end())
471 if (iter != requestedColumns.end())
473 requestedColumns.erase (iter);
493 outData.insert (
outData.end(), branchData.begin(), branchData.end());
507 throw std::runtime_error (
"offset column not filled yet: " +
outputColumns.at(1).name);
509 throw std::runtime_error (
"offset column does not match: " +
outputColumns.at(1).name);
548 virtual bool connect (TTree * , std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& offsetColumns, std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
550 auto iter = requestedColumns.find (
outputColumns.at(0).name);
551 if (iter == requestedColumns.end())
557 const auto offsetName = iter->second.offsetName;
558 if (offsetName.empty())
559 throw std::runtime_error (
"missing offset column for: " +
outputColumns.at(0).name);
561 requestedColumns.erase (iter);
563 if (
auto offsetIter = offsetColumns.find (offsetName); offsetIter != offsetColumns.end())
566 throw std::runtime_error (
"missing offset column for: " +
outputColumns.at(0).name);
604 std::vector<ColumnarOffsetType>
offsets = {0};
617 virtual bool connect (TTree *
tree, std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& , std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
619 auto iter = requestedColumns.find (
outputColumns.at(0).name);
620 if (iter == requestedColumns.end())
627 throw std::runtime_error (
"offset name mismatch: " + iter->second.offsetName +
" != " +
outputColumns.at(1).name);
629 requestedColumns.erase (iter);
632 if (iter == requestedColumns.end())
634 requestedColumns.erase (iter);
652 for (
auto&
data : branchData)
694 std::vector<ColumnarOffsetType>
offsets = {0};
711 virtual bool connect (TTree *
tree, std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& offsetColumns, std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
713 auto iter = requestedColumns.find (
outputColumns.at(0).name);
714 if (iter == requestedColumns.end())
721 throw std::runtime_error (
"offset name mismatch: " + iter->second.offsetName +
" != " +
outputColumns.at(1).name);
723 if (iter->second.linkTargetNames.size() != 1)
724 throw std::runtime_error (
"expected exactly one link target name for: " +
outputColumns.at(0).name);
728 if (
auto offsetIter = offsetColumns.find (iter->second.linkTargetNames.at(0)); offsetIter != offsetColumns.end())
731 throw std::runtime_error (
"missing offset column: " + iter->second.linkTargetNames.at(0));
733 requestedColumns.erase (iter);
736 if (iter == requestedColumns.end())
738 requestedColumns.erase (iter);
757 throw std::runtime_error (
"target offset column not yet filled for: " +
outputColumns.at(0).name);
758 for (
auto&
data : branchData)
760 for (
auto& element :
data)
762 if (element.isDefault() || (element.key() == 0 && element.index() == 0))
775 throw std::runtime_error(
776 std::format(
"target key mismatch: {:x} != {:x} for {} with element index {}",
843 virtual bool connect (TTree *
tree, std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& , std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
845 auto iter = requestedColumns.find (
outputColumns.at(0).name);
846 if (iter == requestedColumns.end())
853 throw std::runtime_error (
"offset name mismatch: " + iter->second.offsetName +
" != " +
outputColumns.at(1).name);
855 requestedColumns.erase (iter);
858 if (iter == requestedColumns.end())
863 throw std::runtime_error (
"offset name mismatch: " + iter->second.offsetName +
" != " +
outputColumns.at(2).name);
865 requestedColumns.erase (iter);
868 if (iter == requestedColumns.end())
871 requestedColumns.erase (iter);
890 for (
auto& outerData : branchData)
892 for (
auto& innerData : outerData)
939 std::vector<ColumnarOffsetType>
offsets = {0};
956 virtual bool connect (TTree *
tree, std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& offsetColumns, std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
958 auto iter = requestedColumns.find (
outputColumns.at(0).name);
959 if (iter == requestedColumns.end())
966 throw std::runtime_error (
"offset name mismatch: " + iter->second.offsetName +
" != " +
outputColumns.at(1).name);
968 if (iter->second.linkTargetNames.size() != 1)
969 throw std::runtime_error (
"expected exactly one link target name for: " +
outputColumns.at(0).name);
973 if (
auto targetOffsetIter = offsetColumns.find (iter->second.linkTargetNames.at(0)); targetOffsetIter != offsetColumns.end())
976 throw std::runtime_error (
"missing offset column(vector-link): " + iter->second.linkTargetNames.at(0));
978 requestedColumns.erase (iter);
980 if (
auto offsetIter = offsetColumns.find (
outputColumns.at(1).name); offsetIter != offsetColumns.end())
986 if (iter != requestedColumns.end())
989 requestedColumns.erase (iter);
1005 const auto& branchData =
branchReader.getEntry (entry);
1009 throw std::runtime_error (
"target offset column not yet filled for: " +
outputColumns.at(0).name);
1010 for (
auto& element : branchData)
1012 if (element.isDefault() || (element.key() == 0 && element.index() == 0))
1025 throw std::runtime_error (
"target key mismatch: " + std::to_string (element.key()) +
" != " + std::to_string (
targetKey) +
" for " +
outputColumns.at(0).name);
1034 throw std::runtime_error (
"offset column not filled yet: " +
outputColumns.at(1).name);
1036 throw std::runtime_error (
"offset column does not match: " +
outputColumns.at(1).name);
1076 template<
typename T>
1102 virtual bool connect (TTree *
tree, std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& offsetColumns, std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
1104 auto iter = requestedColumns.find (
outputColumns.at(0).name);
1105 if (iter == requestedColumns.end())
1114 throw std::runtime_error (
"offset name mismatch: " + iter->second.offsetName +
" != " +
outputColumns.at(1).name);
1116 const auto& linkContainers = iter->second.linkTargetNames;
1117 for (
const auto&
container : linkContainers)
1122 throw std::runtime_error (
"no key known for link container: " +
container);
1123 if (
auto targetOffsetIter = offsetColumns.find (
container); targetOffsetIter != offsetColumns.end())
1126 throw std::runtime_error (
"missing offset column: " +
container);
1129 requestedColumns.erase (iter);
1131 if (
auto offsetIter = offsetColumns.find (
outputColumns.at(1).name); offsetIter != offsetColumns.end())
1137 if (iter != requestedColumns.end())
1140 requestedColumns.erase (iter);
1144 if (iter != requestedColumns.end())
1147 requestedColumns.erase (iter);
1164 auto branchDataKey =
branchReaderKey.getEntry (entry, branchDataSize);
1170 if (targetOffsetColumn->size() <=
offsets.size())
1171 throw std::runtime_error (
"target offset column not yet filled for: " +
outputColumns.at(0).name);
1175 if (branchDataIndex[
index] ==
static_cast<UInt_t
>(-1))
1182 keyIndex = std::distance(
targetKeys.begin(), keyIter);
1187 std::cout <<
"assume target key for " <<
outputColumns.at(0).name <<
" is " << std::hex << branchDataKey[
index] << std::dec << std::endl;
1188 }
else if (branchDataKey[
index] != 0)
1190 std::ostringstream
error;
1191 error <<
"target key mismatch: read " << std::hex << branchDataKey[
index];
1192 error <<
", expected one of";
1194 error <<
" " << key;
1196 throw std::runtime_error (std::move (
error).
str());
1204 auto targetOffset = targetOffsetColumn.at (
offsets.size()-1);
1206 linkIndex += targetOffset;
1207 if (linkIndex >= targetOffsetColumn.at(
offsets.size()))
1208 throw std::runtime_error (std::format (
"index out of range for link: {} >= {} (base index {})",
outputColumns.at(0).name, linkIndex, targetOffsetColumn.at(
offsets.size()), targetOffset));
1217 throw std::runtime_error (
"offset column not filled yet: " +
outputColumns.at(1).name);
1219 throw std::runtime_error (
"offset column does not match: " +
outputColumns.at(1).name);
1261 template<
typename T>
1278 std::unordered_map<SG::sgkey_t,std::unordered_set<std::string>>
unknownKeys;
1293 for (
auto& [key, forbiddenContainer] :
unknownKeys)
1295 std::cout <<
"unknown key: " << std::hex << key << std::dec <<
", allowed containers:";
1298 if (forbiddenContainer.find (
container) == forbiddenContainer.end())
1301 std::cout << std::endl;
1305 virtual bool connect (TTree *
tree, std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& offsetColumns, std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
1307 auto iter = requestedColumns.find (
outputColumns.at(0).name);
1308 if (iter == requestedColumns.end())
1315 throw std::runtime_error (
"offset name mismatch: " + iter->second.offsetName +
" != " +
outputColumns.at(1).name);
1317 if (
containers.empty() || iter->second.variantLinkKeyColumn.empty())
1318 throw std::runtime_error (
"no variant link containers for: " +
outputColumns.at(0).name);
1319 if (iter->second.variantLinkKeyColumn !=
outputColumns.at(2).name)
1320 throw std::runtime_error (
"variant link key column mismatch: " + iter->second.variantLinkKeyColumn +
" != " +
outputColumns.at(2).name);
1325 if (!offsetColumns.contains (
container))
1326 throw std::runtime_error (
"missing offset column(variant-link): " +
container);
1338 requestedColumns.erase (iter);
1341 if (iter != requestedColumns.end())
1344 requestedColumns.erase (iter);
1348 if (iter != requestedColumns.end())
1351 requestedColumns.erase (iter);
1366 const auto& branchData =
branchReader.getEntry (entry);
1369 for (
auto&
data : branchData)
1371 for (
auto& element :
data)
1373 if (element.isDefault() || (element.key() == 0 && element.index() == 0))
1379 for (std::size_t i = 0; i <
containers.size(); ++i)
1384 throw std::runtime_error (
"invalid index: " + std::to_string (element.index()) +
" in container: " +
containers[i] +
" with size: " + std::to_string (
containerOffsets[i]->back()));
1387 throw std::runtime_error (
"container offset not yet filled for: " +
containers[i]);
1397 auto& forbiddenContainers =
unknownKeys[element.key()];
1398 for (std::size_t i = 0; i <
containers.size(); ++i)
1466 virtual bool connect (TTree *
tree, std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& , std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
1468 auto iter = requestedColumns.find (
outputColumns.at(0).name);
1469 if (iter == requestedColumns.end())
1476 throw std::runtime_error (
"offset name mismatch: " + iter->second.offsetName +
" != " +
outputColumns.at(1).name);
1478 requestedColumns.erase (iter);
1481 if (iter == requestedColumns.end())
1486 requestedColumns.erase (iter);
1489 if (iter != requestedColumns.end())
1492 requestedColumns.erase (iter);
1508 const auto& branchData =
branchReader.getEntry (entry);
1511 for (
auto&
data : branchData)
1560 outputColumns.push_back ({.name = val_columnName, .isOffset =
true});
1561 outputColumns.push_back ({.name = val_columnName +
".name.data"});
1562 outputColumns.push_back ({.name = val_columnName +
".name.offset", .isOffset =
true});
1563 outputColumns.push_back ({.name = val_columnName +
".nameHash"});
1566 virtual bool connect (TTree * , std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>&
offsetColumns, std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
1568 if (
auto iter = requestedColumns.find (
outputColumns.at(0).name);
1569 iter != requestedColumns.end())
1570 requestedColumns.erase (iter);
1575 if (
auto iter = requestedColumns.find (
outputColumns.at(1).name);
1576 iter != requestedColumns.end())
1579 requestedColumns.erase (iter);
1582 if (
auto iter = requestedColumns.find (
outputColumns.at(2).name);
1583 iter != requestedColumns.end())
1586 requestedColumns.erase (iter);
1589 if (
auto iter = requestedColumns.find (
outputColumns.at(3).name);
1590 iter != requestedColumns.end())
1593 requestedColumns.erase (iter);
1597 throw std::runtime_error (
"duplicate size column: " +
outputColumns.at(0).name);
1619 namesHash.push_back (std::hash<std::string> () (termName));
1663 virtual bool connect (TTree *
tree, std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& , std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
1665 auto iter = requestedColumns.find (
outputColumns.at(0).name);
1666 if (iter == requestedColumns.end())
1673 throw std::runtime_error (
"offset name mismatch: " + iter->second.offsetName +
" != " +
outputColumns.at(1).name);
1675 requestedColumns.erase (iter);
1678 if (iter == requestedColumns.end())
1683 requestedColumns.erase (iter);
1697 const auto& branchData =
branchReader.getEntry (entry);
1700 for (
auto data : branchData)
1739 ColumnarPhysLiteTest ::
1740 ColumnarPhysLiteTest ()
1742 static std::once_flag flag;
1743 std::call_once (flag, [] ()
1745#ifdef XAOD_STANDALONE
1752 auto *fileName = getenv (
"ASG_TEST_FILE_LITE_MC");
1753 if (fileName ==
nullptr)
1754 throw std::runtime_error (
"missing ASG_TEST_FILE_LITE_MC");
1755 file.reset (TFile::Open (fileName,
"READ"));
1757 throw std::runtime_error (
"failed to open file");
1758 tree =
dynamic_cast<TTree*
> (
file->Get (
"CollectionTree"));
1760 throw std::runtime_error (
"failed to open tree");
1763 ColumnarPhysLiteTest :: ~ColumnarPhysLiteTest () =
default;
1765 std::string ColumnarPhysLiteTest :: makeUniqueName ()
1767 static std::atomic<unsigned>
index = 0;
1768 return "UniquePhysliteTestTool" + std::to_string(++
index);
1771 bool ColumnarPhysLiteTest ::
1777 void ColumnarPhysLiteTest :: setupKnownColumns (
const TestDefinition& testDefinition)
1781 knownColumns.push_back (std::make_shared<ColumnDataEventCount> ());
1783 tree->SetMakeClass (1);
1785 std::unordered_map<std::string,TBranch*> branches;
1787 TIter branchIter (
tree->GetListOfBranches());
1788 TObject *obj =
nullptr;
1789 while ((obj = branchIter()))
1791 TBranch *branch =
nullptr;
1792 if ((branch =
dynamic_cast<TBranch*
>(obj)))
1794 branches.emplace (branch->GetName(), branch);
1795 TIter subBranchIter (branch->GetListOfBranches());
1796 while ((obj = subBranchIter()))
1798 if (
auto subBranch =
dynamic_cast<TBranch*
>(obj))
1799 branches.emplace (subBranch->GetName(), subBranch);
1805 for (
const auto& [name, branch] : branches)
1807 if (name.find (
"AuxDyn.") != std::string::npos ||
1808 name.find (
"Aux.") != std::string::npos)
1810 TClass *branchClass =
nullptr;
1811 EDataType branchType {};
1812 branch->GetExpectedType (branchClass, branchType);
1813 if (branchClass ==
nullptr)
1838 if (*branchClass->GetTypeInfo() ==
typeid(std::vector<float>))
1841 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<char>))
1844 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::int8_t>))
1847 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::uint8_t>))
1850 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::int16_t>))
1853 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::uint16_t>))
1856 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::int32_t>))
1859 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::uint32_t>))
1862 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::int64_t>))
1865 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::uint64_t>))
1868 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::vector<float>>))
1871 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::vector<std::int32_t>>))
1874 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::vector<std::uint64_t>>))
1877 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::vector<std::vector<std::size_t>>>))
1880 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::vector<std::vector<unsigned char>>>))
1883 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::string>))
1885 knownColumns.push_back (std::make_shared<ColumnDataMetNames> (branch->GetName()));
1897 knownColumns.push_back (std::make_shared<ColumnDataSamplingPattern> (
"egammaClusters"));
1937 using namespace asg::msgUserCode;
1939 std::unordered_map<std::string,ColumnInfo> requestedColumns;
1941 requestedColumns[column.name] = std::move (column);
1944 std::cout <<
"requested columns: " << name << std::endl;
1952 std::set<std::string> unclaimedColumns;
1953 for (
auto& column : requestedColumns)
1955 if (!column.second.isOptional)
1956 unclaimedColumns.insert (column.first);
1958 std::cout <<
"optional column not claimed: " << column.first << std::endl;
1962 const auto& info = requestedColumns.at (columnName);
1965 auto offsetIter = std::find_if (
usedColumns.begin(),
usedColumns.end(), [&] (
const std::shared_ptr<TestUtils::IColumnData>& column)
1967 for (auto& output : column->outputColumns)
1969 if (output.name == info.offsetName)
1976 std::shared_ptr<TestUtils::IColumnData> myColumn;
1977 if (*info.type ==
typeid(
float))
1978 myColumn = std::make_shared<TestUtils::ColumnDataOutVector<float>> (info.name, 0);
1979 else if (*info.type ==
typeid(
char))
1980 myColumn = std::make_shared<TestUtils::ColumnDataOutVector<char>> (info.name, 0);
1981 else if (*info.type ==
typeid(std::uint16_t))
1982 myColumn = std::make_shared<TestUtils::ColumnDataOutVector<std::uint16_t>> (info.name, 0);
1983 else if (*info.type ==
typeid(std::uint64_t))
1984 myColumn = std::make_shared<TestUtils::ColumnDataOutVector<std::uint64_t>> (info.name, 0);
1987 ANA_MSG_WARNING (
"unhandled column type: " << info.name <<
" " << info.type->name());
1993 ANA_MSG_WARNING (
"failed to connect dynamic output column: " << info.name);
1999 if (!unclaimedColumns.empty())
2001 std::string message =
"columns not claimed:";
2002 for (
auto& column : unclaimedColumns)
2003 message +=
" " + column;
2004 throw std::runtime_error (message);
2010 using namespace asg::msgUserCode;
2013 if (!testDefinition.
sysName.empty())
2017 throw std::runtime_error (
"tool does not support systematics");
2018 std::cout <<
"applying systematic variation: " << testDefinition.
sysName << std::endl;
2020 throw std::runtime_error (
"failed to apply systematic variation: " + testDefinition.
sysName);
2033 Benchmark benchmarkCall (testDefinition.
name, userConfiguration.batchSize);
2034 Benchmark benchmarkCall2 (testDefinition.
name +
"(call2)", userConfiguration.batchSize);
2035 Benchmark benchmarkCheck (testDefinition.
name +
"(column check)", userConfiguration.batchSize);
2040 const auto startTime = std::chrono::high_resolution_clock::now();
2041 bool endLoop =
false;
2042 for (; !endLoop; ++entry)
2053 if ((entry + 1) % userConfiguration.batchSize == 0)
2058 column->collectColumnData ();
2061 column->setData (toolColumnData);
2068 if (userConfiguration.runToolTwice)
2075 column->clearColumns ();
2076 if ((std::chrono::high_resolution_clock::now() - startTime) > userConfiguration.targetTime)
2081 column->collectColumnData ();
2085 std::cout <<
"Total entries read: " << entry << std::endl;
2086 const float emptyTime = benchmarkEmpty.
getEntryTime(0).value();
2087 std::cout <<
"Empty benchmark time: " << emptyTime <<
"ns" << std::endl;
2090 std::vector<TestUtils::BranchPerfData> branchPerfData;
2092 summary.name =
"total";
2093 summary.timeRead = 0;
2094 summary.timeUnpack = 0;
2095 summary.timeShallowCopy = 0;
2096 summary.entries = std::nullopt;
2097 summary.nullEntries = std::nullopt;
2100 branchPerfData.push_back (column->getPerfData (emptyTime));
2101 summary.timeRead.value() += branchPerfData.back().timeRead.value_or(0);
2102 summary.timeUnpack.value() += branchPerfData.back().timeUnpack.value_or(0);
2103 summary.timeShallowCopy.value() += branchPerfData.back().timeShallowCopy.value_or(0);
2105 std::sort (branchPerfData.begin(), branchPerfData.end(), [] (
const auto&
a,
const auto& b) {return a.name < b.name;});
2106 branchPerfData.insert (branchPerfData.end(), summary);
2107 const std::size_t nameWidth = std::max_element (branchPerfData.begin(), branchPerfData.end(), [] (
const auto&
a,
const auto& b) {return a.name.size() < b.name.size();})->name.size();
2108 std::string
header = std::format (
"{:{}} | read(ns) | unpack(ns) | size(B) | rate(MB/s) | compression | baskets | entries | null",
"branch name", nameWidth);
2109 std::cout <<
"\n" <<
header << std::endl;
2110 std::cout << std::string (
header.size(),
'-') << std::endl;
2111 for (
auto&
data : branchPerfData)
2113 if (
data.name ==
"total")
2114 std::cout << std::string (
header.size(),
'-') << std::endl;
2115 std::cout << std::format (
"{:{}} |",
data.name, nameWidth);
2117 std::cout << std::format (
"{:>9.0f} |",
data.timeRead.value());
2120 if (
data.timeUnpack)
2121 std::cout << std::format (
"{:>11.1f} |",
data.timeUnpack.value());
2125 std::cout << std::format (
"{:>8.1f} |",
data.entrySize.value());
2128 if (
data.timeRead &&
data.entrySize)
2129 std::cout << std::format (
"{:>11.1f} |", (
data.entrySize.value() / (
data.timeRead.value() * 1e-3 * 1.024 * 1.024)));
2132 if (
data.entrySize &&
data.uncompressedSize)
2133 std::cout << std::format (
"{:>12.2f} |",
float (
data.uncompressedSize.value()) /
data.entrySize.value());
2136 if (
data.numBaskets)
2137 std::cout << std::format (
"{:>8} |",
data.numBaskets.value());
2141 std::cout << std::format (
"{:>8.2f} |",
static_cast<float>(
data.entries.value())/
numberOfEvents);
2144 if (
data.nullEntries &&
data.entries)
2145 std::cout << std::format (
"{:>4.0f}%",
static_cast<float>(
data.nullEntries.value()) /
data.entries.value() * 100.0f);
2146 std::cout << std::endl;
2150 std::vector<TestUtils::ToolPerfData> toolPerfData;
2151 toolPerfData.emplace_back ();
2152 toolPerfData.back().name = testDefinition.
name;
2153 toolPerfData.back().timeCall = benchmarkCall.
getEntryTime(emptyTime);
2154 if (userConfiguration.runToolTwice)
2155 toolPerfData.back().timeCall2 = benchmarkCall2.
getEntryTime(emptyTime);
2156 toolPerfData.back().timeCheck = benchmarkCheck.
getEntryTime(emptyTime);
2160 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();
2161 std::string
header = std::format (
"{:{}} | call(ns) | call2(ns) | check(ns)",
"tool name", nameWidth);
2162 std::cout <<
"\n" <<
header << std::endl;
2163 std::cout << std::string (
header.size(),
'-') << std::endl;
2164 for (
auto&
data : toolPerfData)
2166 std::cout << std::format (
"{:{}} |",
data.name, nameWidth);
2168 std::cout << std::format (
"{:>9.0f} |",
data.timeCall.value());
2172 std::cout << std::format (
"{:>10.0f} |",
data.timeCall2.value());
2176 std::cout << std::format (
"{:>10.1f}",
data.timeCheck.value());
2177 std::cout << std::endl;
2183#ifdef XAOD_STANDALONE
2191#ifdef XAOD_STANDALONE
2192 Benchmark benchmarkEmptyClear (testDefinition.
name +
" empty clear");
2193 Benchmark benchmarkCallClear (testDefinition.
name +
" call clear");
2194 Benchmark benchmarkPrepClear (testDefinition.
name +
" prep clear");
2196 Benchmark benchmarkRepeatCall (testDefinition.
name +
" repeat-call");
2198 Benchmark benchmarkCallCopyRecord (testDefinition.
name +
" call copy-record");
2199 Benchmark benchmarkCallRetrieve (testDefinition.
name +
" call retrieve");
2201 Benchmark benchmarkPrepCopyRecord (testDefinition.
name +
" prep copy-record");
2202 Benchmark benchmarkPrepRetrieve (testDefinition.
name +
" prep retrieve");
2203 Benchmark benchmarkGetEntry (testDefinition.
name +
" getEntry");
2206#ifdef XAOD_STANDALONE
2207 std::cout <<
"known container keys:" << std::endl;
2210 std::cout << std::format (
" {} -> 0x{:x}, 0x{:x} -> {}",
container, event.getHash (
container), key, event.getName (key)) << std::endl;
2214 throw std::runtime_error (
"ColumnarPhysLiteTest: numberOfEvents == 0");
2223 const auto startTime = std::chrono::high_resolution_clock::now();
2224 for (; (std::chrono::high_resolution_clock::now() - startTime) < userConfiguration.targetTime; ++entry)
2233 static const std::string prepPostfix =
"Prep";
2239#ifdef XAOD_STANDALONE
2248 static const std::string callPostfix =
"Call";
2254 if (userConfiguration.runToolTwice)
2260#ifdef XAOD_STANDALONE
2269 std::cout <<
"Total entries read: " << entry << std::endl;
char data[hepevt_bytes_allocation_ATLAS]
A number of constexpr particle constants to avoid hardcoding them directly in various places.
ServiceHandle< StoreGateSvc > & evtStore()
The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.
Class to wrap a set of SystematicVariations.
a class that holds the columnar data for a single call
void checkData() const
do a basic check of the data vector
void callNoCheck(const IColumnarTool &tool)
call the tool with the assembled data, without performing any checks on the data
the header information for the entire columnar data vector
this is a simple benchmarking helper class wrapping timers from std::chrono
std::optional< float > getEntryTime(float emptyTime) const
std::string columnName() const
BranchReaderArray(const std::string &val_branchName)
std::string containerName() const
void connectTree(TTree *tree)
std::vector< T > m_dataVec
std::span< const T > getEntry(Long64_t entry, std::size_t size)
std::optional< unsigned > numBaskets()
BranchReaderArray(const BranchReaderArray &)=delete
std::optional< float > uncompressedSize() const
std::optional< float > entrySize() const
BranchReaderArray & operator=(const BranchReaderArray &)=delete
void setIsStatic(bool isStatic)
const std::string & branchName() const
std::optional< float > entrySize() const
std::string columnName() const
BranchReader(const BranchReader &)=delete
BranchReader(const std::string &val_branchName)
std::string containerName() const
std::optional< unsigned > numBaskets()
BranchReader & operator=(const BranchReader &)=delete
void connectTree(TTree *tree)
const T & getEntry(Long64_t entry)
std::optional< float > uncompressedSize() const
const T & getCachedEntry() const
virtual void collectColumnData()=0
std::vector< OutputColumnInfo > outputColumns
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &offsetColumns, std::unordered_map< std::string, ColumnInfo > &requestedColumns)=0
virtual void clearColumns()=0
virtual ~IColumnData() noexcept=default
virtual void getEntry(Long64_t entry)=0
virtual void setData(TestUtils::ToolWrapperData &tool)=0
virtual BranchPerfData getPerfData(float emptyTime)=0
Tool for accessing xAOD files outside of Athena.
A relatively simple transient store for objects created in analysis.
IAppMgrUI * Init(const char *options="POOLRootAccess/basic.opts")
Bootstraps (creates and configures) the Gaudi Application with the provided options file.
constexpr double muonMassInMeV
the mass of the muon (in MeV)
uint32_t sgkey_t
Type used for hashed StoreGate key+CLID pairs.
void runXaodArrayTest(const UserConfiguration &userConfiguration, const TestDefinition &testDefinition, TFile *file)
static const std::unordered_map< std::string, SG::sgkey_t > knownKeys
constexpr unsigned columnarAccessMode
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
constexpr ColumnarOffsetType invalidObjectIndex
the value for an invalid element index
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
std::size_t erase_if(T_container &container, T_Func pred)
@ Jet
The object is a jet.
@ Muon
The object is a muon.
StatusCode Init(const char *appname)
Function initialising ROOT/PyROOT for using the ATLAS EDM.
a struct that contains meta-information about each column that's needed to interface the column with ...
std::size_t LinkIndexType
the type used for columns that represent element links
static constexpr LinkIndexType invalidLinkValue
the value used for an invalid link (a.k.a. empty/null link)
static LinkIndexType mergeLinkKeyIndex(LinkIndexType key, LinkIndexType index)
merge a key and index value into a link value
std::vector< std::shared_ptr< TestUtils::IColumnData > > knownColumns
std::vector< std::shared_ptr< TestUtils::IColumnData > > usedColumns
void setupColumns(ToolColumnVectorMap &toolWrapper)
std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > offsetColumns
void setupKnownColumns(const TestUtils::TestDefinition &testDefinition)
std::unique_ptr< TFile > file
the performance data for reading a single branch/column
virtual void setData(TestUtils::ToolWrapperData &tool) override
virtual void getEntry(Long64_t) override
virtual void clearColumns() override
virtual bool connect(TTree *, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
std::array< ColumnarOffsetType, 2 > data
virtual BranchPerfData getPerfData(float) override
virtual void collectColumnData() override
std::vector< char > columnData
virtual void collectColumnData() override
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
std::vector< ColumnarOffsetType > offsets
virtual BranchPerfData getPerfData(float emptyTime) override
virtual void getEntry(Long64_t entry) override
Benchmark benchmarkUnpack
virtual void setData(TestUtils::ToolWrapperData &tool) override
ColumnDataMetNames(const std::string &val_branchName)
std::vector< std::size_t > columnHashData
BranchReader< std::vector< std::string > > branchReader
virtual void clearColumns() override
ColumnDataOutVector(const std::string &val_columnName, const T &val_defaultValue)
virtual void collectColumnData() override
virtual BranchPerfData getPerfData(float) override
virtual void setData(TestUtils::ToolWrapperData &tool) override
const std::vector< ColumnarOffsetType > * offsetColumn
virtual void clearColumns() override
virtual void getEntry(Long64_t) override
virtual bool connect(TTree *, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &offsetColumns, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
std::vector< std::size_t > namesHash
virtual void clearColumns() override
virtual void getEntry(Long64_t) override
virtual void collectColumnData() override
const std::vector< ColumnarOffsetType > * offsetColumns
virtual BranchPerfData getPerfData(float) override
virtual bool connect(TTree *, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &offsetColumns, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
std::vector< char > namesData
std::vector< std::string > termNames
ColumnDataOutputMet(const std::string &val_columnName, std::vector< std::string > val_termNames)
std::vector< ColumnarOffsetType > namesOffsets
std::vector< ColumnarOffsetType > offsets
virtual void setData(TestUtils::ToolWrapperData &tool) override
BranchReader< xAOD::CaloClusterContainer > branchReader
virtual void clearColumns() override
virtual void getEntry(Long64_t entry) override
std::vector< std::uint32_t > columnData
Benchmark benchmarkUnpack
virtual BranchPerfData getPerfData(float emptyTime) override
ColumnDataSamplingPattern(const std::string &val_branchName)
std::vector< ColumnarOffsetType > offsets
virtual void setData(TestUtils::ToolWrapperData &tool) override
virtual void collectColumnData() override
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
virtual void clearColumns() override
virtual void setData(TestUtils::ToolWrapperData &tool) override
virtual void collectColumnData() override
virtual BranchPerfData getPerfData(float emptyTime) override
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
ColumnDataScalar(const std::string &val_branchName)
BranchReader< T > branchReader
virtual void getEntry(Long64_t entry) override
Benchmark benchmarkUnpack
virtual void getEntry(Long64_t entry) override
virtual void setData(TestUtils::ToolWrapperData &tool) override
virtual void collectColumnData() override
BranchReader< std::vector< ElementLink< T > > > branchReader
ColumnDataVectorLink(const std::string &val_branchName)
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &offsetColumns, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
virtual BranchPerfData getPerfData(float emptyTime) override
Benchmark benchmarkUnpack
const std::vector< ColumnarOffsetType > * offsetColumn
std::string targetContainerName
std::vector< typename CM::LinkIndexType > columnData
const std::vector< ColumnarOffsetType > * targetOffsetColumn
std::vector< ColumnarOffsetType > offsets
virtual void clearColumns() override
BranchReader< Int_t > branchReaderSize
const std::vector< ColumnarOffsetType > * offsetColumn
std::vector< typename CM::LinkKeyType > keyColumnData
BranchReaderArray< UInt_t > branchReaderIndex
std::vector< typename CM::LinkIndexType > columnData
virtual void setData(TestUtils::ToolWrapperData &tool) override
std::vector< ColumnarOffsetType > offsets
std::vector< SG::sgkey_t > targetKeys
std::vector< const std::vector< ColumnarOffsetType > * > targetOffsetColumns
virtual BranchPerfData getPerfData(float emptyTime) override
virtual void collectColumnData() override
BranchReaderArray< UInt_t > branchReaderKey
ColumnDataVectorSplitLink(const std::string &val_branchName)
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &offsetColumns, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
virtual void getEntry(Long64_t entry) override
virtual void clearColumns() override
Benchmark benchmarkUnpack
Benchmark benchmarkUnpack
std::vector< ColumnarOffsetType > offsets
virtual void getEntry(Long64_t entry) override
std::string targetContainerName
ColumnDataVectorVectorLink(const std::string &val_branchName)
BranchReader< std::vector< std::vector< ElementLink< T > > > > branchReader
virtual BranchPerfData getPerfData(float emptyTime) override
virtual void setData(TestUtils::ToolWrapperData &tool) override
virtual void collectColumnData() override
std::vector< typename CM::LinkIndexType > columnData
virtual void clearColumns() override
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &offsetColumns, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
const std::vector< ColumnarOffsetType > * targetOffsetColumn
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &offsetColumns, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
std::vector< std::string > containers
std::vector< const std::vector< ColumnarOffsetType > * > containerOffsets
ColumnDataVectorVectorVariantLink(const std::string &val_branchName)
std::vector< SG::sgkey_t > containerKeys
virtual void clearColumns() override
virtual void getEntry(Long64_t entry) override
Benchmark benchmarkUnpack
virtual BranchPerfData getPerfData(float emptyTime) override
std::vector< ColumnarOffsetType > offsets
std::vector< typename CM::LinkIndexType > columnData
virtual void collectColumnData() override
virtual void setData(TestUtils::ToolWrapperData &tool) override
BranchReader< std::vector< std::vector< ElementLink< T > > > > branchReader
~ColumnDataVectorVectorVariantLink()
std::vector< typename CM::LinkKeyType > keysColumn
std::unordered_map< SG::sgkey_t, std::unordered_set< std::string > > unknownKeys
std::vector< ColumnarOffsetType > outerOffsets
virtual void clearColumns() override
std::vector< T > columnData
std::vector< ColumnarOffsetType > innerOffsets
virtual void collectColumnData() override
virtual void setData(TestUtils::ToolWrapperData &tool) override
virtual BranchPerfData getPerfData(float emptyTime) override
Benchmark benchmarkUnpack
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
BranchReader< std::vector< std::vector< std::vector< T > > > > branchReader
virtual void getEntry(Long64_t entry) override
ColumnDataVectorVectorVector(const std::string &val_branchName)
std::vector< T > columnData
virtual BranchPerfData getPerfData(float emptyTime) override
virtual void clearColumns() override
virtual void setData(TestUtils::ToolWrapperData &tool) override
virtual void collectColumnData() override
std::vector< ColumnarOffsetType > offsets
BranchReader< std::vector< std::vector< T > > > branchReader
Benchmark benchmarkUnpack
ColumnDataVectorVector(const std::string &val_branchName)
virtual void getEntry(Long64_t entry) override
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
std::vector< ColumnarOffsetType > offsets
BranchReader< std::vector< T > > branchReader
virtual void setData(TestUtils::ToolWrapperData &tool) override
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &offsetColumns, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
virtual BranchPerfData getPerfData(float emptyTime) override
virtual void getEntry(Long64_t entry) override
Benchmark benchmarkUnpack
ColumnDataVector(const std::string &val_branchName)
virtual void collectColumnData() override
const std::vector< ColumnarOffsetType > * offsetColumn
virtual void clearColumns() override
the general configuration for a single test
std::string sysName
the systematic variation to apply (empty for nominal)
IXAODToolCaller * xAODToolCaller
the callback for calling the tool in xAOD mode
std::vector< std::string > metTermNames
the MET output term names (if empty, MET output columns are omitted)
std::string name
the name identifier for the test
std::vector< std::pair< std::string, std::string > > containerRenames
the container name remappings to apply
asg::AsgTool * tool
the tool being tested
static UserConfiguration fromEnvironment()
create a UserConfiguration, loading from the file pointed to by the COLUMNAR_TEST_CONFIG environment ...