35 : fPageSource(std::move(pageSource))
38 auto descriptorGuard =
fPageSource->GetSharedDescriptorGuard();
51 fUncompressedSize = 0;
53 std::vector<DescriptorId_t> clusterIds;
54 for (
const auto &cgDesc : fDescriptor.GetClusterGroupIterable()) {
56 clusterIds.insert(clusterIds.end(), cgDesc.GetClusterIds().begin(), cgDesc.GetClusterIds().end());
59 for (
const auto &colDesc : fDescriptor.GetColumnIterable()) {
60 if (colDesc.IsAliasColumn())
63 auto colId = colDesc.GetPhysicalId();
68 std::uint64_t nElems = 0;
69 std::vector<std::uint64_t> compressedPageSizes{};
71 for (
auto cid : clusterIds) {
72 const auto &clusterDescriptor = fDescriptor.GetClusterDescriptor(cid);
73 if (!clusterDescriptor.ContainsColumn(colId)) {
77 auto columnRange = clusterDescriptor.GetColumnRange(colId);
78 if (columnRange.IsSuppressed())
81 nElems += columnRange.GetNElements();
83 if (!fCompressionSettings && columnRange.GetCompressionSettings()) {
84 fCompressionSettings = columnRange.GetCompressionSettings();
85 }
else if (fCompressionSettings && columnRange.GetCompressionSettings() &&
86 (*fCompressionSettings != *columnRange.GetCompressionSettings())) {
91 std::to_string(*fCompressionSettings) +
" vs " +
92 std::to_string(*columnRange.GetCompressionSettings()) +
93 ") for column with physical ID " + std::to_string(colId)));
96 const auto &pageRange = clusterDescriptor.GetPageRange(colId);
98 for (
const auto &page : pageRange.GetPageInfos()) {
99 compressedPageSizes.emplace_back(page.GetLocator().GetNBytesOnStorage());
100 fUncompressedSize += page.GetNElements() * elemSize;
105 std::accumulate(compressedPageSizes.begin(), compressedPageSizes.end(),
static_cast<std::uint64_t
>(0));
106 fColumnInfo.emplace(colId,
RColumnInspector(colDesc, compressedPageSizes, elemSize, nElems));
113 std::uint64_t compressedSize = 0;
114 std::uint64_t uncompressedSize = 0;
116 for (
const auto &colDescriptor : fDescriptor.GetColumnIterable(fieldId)) {
117 auto colInfo = GetColumnInspector(colDescriptor.GetPhysicalId());
118 compressedSize += colInfo.GetCompressedSize();
119 uncompressedSize += colInfo.GetUncompressedSize();
122 for (
const auto &subFieldDescriptor : fDescriptor.GetFieldIterable(fieldId)) {
123 auto subFieldId = subFieldDescriptor.GetId();
125 auto subFieldInfo = CollectFieldTreeInfo(subFieldId);
127 compressedSize += subFieldInfo.GetCompressedSize();
128 uncompressedSize += subFieldInfo.GetUncompressedSize();
131 auto fieldInfo =
RFieldTreeInspector(fDescriptor.GetFieldDescriptor(fieldId), compressedSize, uncompressedSize);
132 fFieldTreeInfo.emplace(fieldId, fieldInfo);
136std::vector<ROOT::DescriptorId_t>
139 std::vector<ROOT::DescriptorId_t> colIds;
140 std::deque<ROOT::DescriptorId_t> fieldIdQueue{fieldId};
142 while (!fieldIdQueue.empty()) {
143 auto currId = fieldIdQueue.front();
144 fieldIdQueue.pop_front();
146 for (
const auto &col : fDescriptor.GetColumnIterable(currId)) {
147 if (col.IsAliasColumn()) {
151 colIds.emplace_back(col.GetPhysicalId());
154 for (
const auto &fld : fDescriptor.GetFieldIterable(currId)) {
155 fieldIdQueue.push_back(fld.GetId());
162std::unique_ptr<ROOT::Experimental::RNTupleInspector>
166 return std::unique_ptr<RNTupleInspector>(
new RNTupleInspector(std::move(pageSource)));
169std::unique_ptr<ROOT::Experimental::RNTupleInspector>
173 return std::unique_ptr<RNTupleInspector>(
new RNTupleInspector(std::move(pageSource)));
178 if (!fCompressionSettings)
181 int algorithm = *fCompressionSettings / 100;
182 int level = *fCompressionSettings - (algorithm * 100);
185 " (level " + std::to_string(level) +
")";
193 if (physicalColumnId > fDescriptor.GetNPhysicalColumns()) {
194 throw RException(
R__FAIL(
"No column with physical ID " + std::to_string(physicalColumnId) +
" present"));
197 return fColumnInfo.at(physicalColumnId);
202 size_t typeCount = 0;
204 for (
auto &[colId, colInfo] : fColumnInfo) {
205 if (colInfo.GetType() == colType) {
213std::vector<ROOT::DescriptorId_t>
216 std::vector<ROOT::DescriptorId_t> colIds;
218 for (
const auto &[colId, colInfo] : fColumnInfo) {
219 if (colInfo.GetType() == colType)
220 colIds.emplace_back(colId);
228 std::set<ROOT::ENTupleColumnType> colTypes;
230 for (
const auto &[colId, colInfo] : fColumnInfo) {
231 colTypes.emplace(colInfo.GetType());
234 return std::vector(colTypes.begin(), colTypes.end());
239 struct ColumnTypeInfo {
240 std::uint64_t nElems = 0;
241 std::uint64_t compressedSize = 0;
242 std::uint64_t uncompressedSize = 0;
243 std::uint64_t nPages = 0;
244 std::uint32_t count = 0;
256 float GetCompressionFactor()
const
258 if (compressedSize == 0)
260 return static_cast<float>(uncompressedSize) /
static_cast<float>(compressedSize);
264 std::map<ENTupleColumnType, ColumnTypeInfo> colTypeInfo;
267 for (
const auto &[colId, colInfo] : fColumnInfo) {
268 colTypeInfo[colInfo.GetType()] += colInfo;
273 output <<
" column type | count | # elements | compressed bytes | uncompressed bytes | compression ratio | "
275 <<
"----------------|---------|-------------|------------------|--------------------|-------------------|-"
277 for (
const auto &[colType, typeInfo] : colTypeInfo)
279 << typeInfo.count <<
" |" << std::setw(12) << typeInfo.nElems <<
" |" << std::setw(17)
280 << typeInfo.compressedSize <<
" |" << std::setw(19) << typeInfo.uncompressedSize <<
" |" << std::fixed
281 << std::setprecision(3) << std::setw(18) << typeInfo.GetCompressionFactor() <<
" |" << std::setw(6)
282 << typeInfo.nPages <<
" \n";
285 output <<
"columnType,count,nElements,compressedSize,uncompressedSize,compressionFactor,nPages\n";
286 for (
const auto &[colType, typeInfo] : colTypeInfo) {
288 <<
"," << typeInfo.compressedSize <<
"," << typeInfo.uncompressedSize <<
"," << std::fixed
289 << std::setprecision(3) << typeInfo.GetCompressionFactor() <<
"," << typeInfo.nPages <<
'\n';
292 default:
R__ASSERT(
false &&
"Invalid print format");
298 std::string_view histName, std::string_view histTitle)
300 if (histName.empty()) {
310 if (histTitle.empty()) {
320 auto hist = std::make_unique<TH1D>(std::string(histName).c_str(), std::string(histTitle).c_str(), 1, 0, 1);
323 for (
const auto &[colId, colInfo] : fColumnInfo) {
340 std::string histName, std::string histTitle,
size_t nBins)
342 if (histTitle.empty())
343 histTitle =
"Page size distribution for column with ID " + std::to_string(physicalColumnId);
345 return GetPageSizeDistribution({physicalColumnId}, histName, histTitle, nBins);
349 std::string histName,
350 std::string histTitle,
size_t nBins)
352 if (histName.empty())
354 if (histTitle.empty())
358 auto perTypeHist = GetPageSizeDistribution({colType}, histName, histTitle, nBins);
360 if (perTypeHist->GetNhists() < 1)
361 return std::make_unique<TH1D>(histName.c_str(), histTitle.c_str(), 64, 0, 0);
363 auto hist = std::unique_ptr<TH1D>(
dynamic_cast<TH1D *
>(perTypeHist->GetHists()->First()));
365 hist->SetName(histName.c_str());
366 hist->SetTitle(histTitle.c_str());
367 hist->SetXTitle(
"Page size (B)");
368 hist->SetYTitle(
"N_{pages}");
374 std::string histName, std::string histTitle,
size_t nBins)
376 auto hist = std::make_unique<TH1D>();
378 if (histName.empty())
379 histName =
"pageSizeHist";
380 hist->SetName(histName.c_str());
381 if (histTitle.empty())
382 histTitle =
"Page size distribution";
383 hist->SetTitle(histTitle.c_str());
384 hist->SetXTitle(
"Page size (B)");
385 hist->SetYTitle(
"N_{pages}");
387 std::vector<std::uint64_t> pageSizes;
388 std::for_each(colIds.begin(), colIds.end(), [
this, &pageSizes](
const auto colId) {
389 auto colInfo = GetColumnInspector(colId);
390 pageSizes.insert(pageSizes.end(), colInfo.GetCompressedPageSizes().begin(),
391 colInfo.GetCompressedPageSizes().end());
394 if (!pageSizes.empty()) {
395 auto histMinMax = std::minmax_element(pageSizes.begin(), pageSizes.end());
396 hist->SetBins(nBins, *histMinMax.first,
397 *histMinMax.second + ((*histMinMax.second - *histMinMax.first) /
static_cast<double>(nBins)));
399 for (
const auto pageSize : pageSizes) {
400 hist->Fill(pageSize);
407std::unique_ptr<THStack>
409 std::string histName, std::string histTitle,
size_t nBins)
411 if (histName.empty())
412 histName =
"pageSizeHist";
413 if (histTitle.empty())
414 histTitle =
"Per-column type page size distribution";
416 auto stackedHist = std::make_unique<THStack>(histName.c_str(), histTitle.c_str());
418 double histMin = std::numeric_limits<double>::max();
420 std::map<ROOT::ENTupleColumnType, std::vector<std::uint64_t>> pageSizes;
422 std::vector<ROOT::ENTupleColumnType> colTypeVec = colTypes;
423 if (std::empty(colTypes)) {
424 colTypeVec = GetColumnTypes();
427 for (
const auto colType : colTypeVec) {
428 auto colIds = GetColumnsByType(colType);
433 std::vector<std::uint64_t> pageSizesForColType;
434 std::for_each(colIds.cbegin(), colIds.cend(), [
this, &pageSizesForColType](
const auto colId) {
435 auto colInfo = GetColumnInspector(colId);
436 pageSizesForColType.insert(pageSizesForColType.end(), colInfo.GetCompressedPageSizes().begin(),
437 colInfo.GetCompressedPageSizes().end());
439 if (pageSizesForColType.empty())
442 pageSizes.emplace(colType, pageSizesForColType);
444 auto histMinMax = std::minmax_element(pageSizesForColType.begin(), pageSizesForColType.end());
445 histMin = std::min(histMin,
static_cast<double>(*histMinMax.first));
446 histMax = std::max(histMax,
static_cast<double>(*histMinMax.second));
449 for (
const auto &[colType, pageSizesForColType] : pageSizes) {
450 auto hist = std::make_unique<TH1D>(
453 histMax + ((histMax - histMin) /
static_cast<double>(nBins)));
455 for (
const auto pageSize : pageSizesForColType) {
456 hist->Fill(pageSize);
459 stackedHist->Add(hist.release());
466 std::initializer_list<ROOT::ENTupleColumnType> colTypes, std::string_view histName, std::string_view histTitle,
469 if (histName.empty())
470 histName =
"pagesPerClusterHist";
471 if (histTitle.empty())
472 histTitle =
"#pages per cluster";
474 auto stackedHist = std::make_unique<THStack>(std::string(histName).c_str(), std::string(histTitle).c_str());
476 std::vector<std::unordered_map<ENTupleColumnType, std::uint64_t>> pagesPerClusterPerColumnType;
478 std::vector<ROOT::ENTupleColumnType> colTypeVec = colTypes;
479 if (std::empty(colTypes)) {
480 colTypeVec = GetColumnTypes();
483 R__ASSERT(fDescriptor.GetNClusters() == fDescriptor.GetNActiveClusters());
484 for (
const auto &clDesc : fDescriptor.GetActiveClusterIterable()) {
485 auto &pagesPerColumnTypeInThisCluster = pagesPerClusterPerColumnType.emplace_back();
486 for (
const auto &colRange : clDesc.GetColumnRangeIterable()) {
487 const auto colId = colRange.GetPhysicalColumnId();
488 const auto &colDesc = fDescriptor.GetColumnDescriptor(colId);
489 const auto nPages = clDesc.GetPageRange(colId).GetPageInfos().size();
490 auto &nPagesForThisType = pagesPerColumnTypeInThisCluster[colDesc.GetType()];
491 nPagesForThisType += nPages;
495 double histMin = std::numeric_limits<double>::max();
497 for (
const auto &pagesPerType : pagesPerClusterPerColumnType) {
498 auto [min, max] = std::minmax_element(pagesPerType.begin(), pagesPerType.end(),
499 [](
const auto &
a,
const auto &
b) { return a.second < b.second; });
500 histMin = std::min<double>(histMin, min->second);
501 histMax = std::max<double>(histMax, max->second);
505 for (
const auto &pagesPerType : pagesPerClusterPerColumnType) {
506 for (
const auto &[colType, nPages] : pagesPerType) {
507 auto &hist = histsPerType[
static_cast<std::size_t
>(colType)];
511 histMin, histMax + ((histMax - histMin) /
static_cast<double>(nBins)));
517 for (
auto &hist : histsPerType) {
519 stackedHist->Add(hist.release());
531 if (fieldId >= fDescriptor.GetNFields()) {
532 throw RException(
R__FAIL(
"No field with ID " + std::to_string(fieldId) +
" present"));
535 return fFieldTreeInfo.at(fieldId);
541 auto fieldId = fDescriptor.FindFieldId(fieldName);
544 throw RException(
R__FAIL(
"Could not find field `" + std::string(fieldName) +
"`"));
547 return GetFieldTreeInspector(fieldId);
551 bool includeSubfields)
const
553 size_t typeCount = 0;
555 for (
auto &[fldId, fldInfo] : fFieldTreeInfo) {
556 if (!includeSubfields && fldInfo.GetDescriptor().GetParentId() != fDescriptor.GetFieldZeroId()) {
560 if (std::regex_match(fldInfo.GetDescriptor().GetTypeName(), typeNamePattern)) {
568std::vector<ROOT::DescriptorId_t>
571 std::vector<ROOT::DescriptorId_t> fieldIds;
573 for (
auto &[fldId, fldInfo] : fFieldTreeInfo) {
575 if (!searchInSubfields && fldInfo.GetDescriptor().GetParentId() != fDescriptor.GetFieldZeroId()) {
579 if (std::regex_match(fldInfo.GetDescriptor().GetFieldName(), fieldNamePattern)) {
580 fieldIds.emplace_back(fldId);
588 std::ostream &output)
const
590 const auto &tupleDescriptor = GetDescriptor();
593 output <<
"digraph D {\n";
594 output <<
"node[shape=box]\n";
596 const std::string &nodeId = (isZeroField) ?
"0" : std::to_string(fieldDescriptor.
GetId() + 1);
600 auto htmlEscape = [&](
const std::string &in) -> std::string {
602 out.reserve(in.size());
603 for (
const char &
c : in) {
605 case '&': out +=
"&";
break;
606 case '<': out +=
"<";
break;
607 case '>': out +=
">";
break;
608 case '\"': out +=
""";
break;
609 case '\'': out +=
"'";
break;
610 default: out +=
c;
break;
616 output << nodeId <<
"[label=<";
618 output <<
"<b>Name: </b>" << htmlEscape(fieldDescriptor.
GetFieldName()) <<
"<br></br>";
619 output <<
"<b>Type: </b>" << htmlEscape(fieldDescriptor.
GetTypeName()) <<
"<br></br>";
620 output <<
"<b>ID: </b>" << std::to_string(fieldDescriptor.
GetId()) <<
"<br></br>";
621 if (description !=
"")
622 output <<
"<b>Description: </b>" << htmlEscape(description) <<
"<br></br>";
624 output <<
"<b>Version: </b>" << version <<
"<br></br>";
626 output <<
"<b>RFieldZero</b>";
628 for (
const auto &childFieldId : fieldDescriptor.
GetLinkIds()) {
629 const auto &childFieldDescriptor = tupleDescriptor.GetFieldDescriptor(childFieldId);
630 output << nodeId +
"->" + std::to_string(childFieldDescriptor.GetId() + 1) +
"\n";
631 PrintFieldTreeAsDot(childFieldDescriptor, output);
639struct SpeedscopeFrame {
641 std::uint64_t fOpeningPosition = 0;
642 std::uint64_t fClosingPosition = 0;
645static void PrintSpeedscopeFrames(
const std::vector<SpeedscopeFrame> &frames, std::ostream &output)
648 output <<
" \"$schema\":\"https://www.speedscope.app/file-format-schema.json\",\n";
649 output <<
" \"shared\":{\n";
650 output <<
" \"frames\":[\n";
652 for (std::size_t i = 0; i < frames.size(); ++i) {
653 output <<
" { \"name\":\"" << frames[i].fString <<
"\" }" << (i + 1 < frames.size() ?
",\n" :
"\n");
658 output <<
" \"profiles\":[\n";
660 output <<
" \"type\":\"evented\",\n";
661 output <<
" \"name\":\"Flattened Timeline\",\n";
662 output <<
" \"unit\":\"bytes\",\n";
663 output <<
" \"startValue\":0,\n";
664 output <<
" \"endValue\":" << frames.back().fClosingPosition <<
",\n";
665 output <<
" \"events\":[\n";
674 std::function<std::size_t(std::size_t, std::uint32_t)> processRecursive = [&](std::size_t nextIdxToProcess,
675 std::uint32_t limit) -> std::size_t {
676 while (nextIdxToProcess < frames.size() && frames[nextIdxToProcess].fOpeningPosition < limit) {
677 const std::size_t currentIdx = nextIdxToProcess;
682 output <<
" {\"type\":\"O\",\"frame\":" << currentIdx
683 <<
",\"at\":" << frames[currentIdx].fOpeningPosition <<
"}";
686 nextIdxToProcess = processRecursive(nextIdxToProcess + 1, frames[currentIdx].fClosingPosition);
688 output <<
",\n {\"type\":\"C\",\"frame\":" << currentIdx
689 <<
",\"at\":" << frames[currentIdx].fClosingPosition <<
"}";
691 return nextIdxToProcess;
694 processRecursive(0, frames.back().fClosingPosition);
709 const auto &tupleDescriptor = GetDescriptor();
711 const auto &rootFieldDescriptor = tupleDescriptor.GetFieldDescriptor(rootId);
713 std::vector<SpeedscopeFrame> frames;
714 std::uint64_t positionCursor = 0;
717 auto visitFieldsRecursive = [&](
auto &self,
const ROOT::RFieldDescriptor &fieldDescriptor) -> std::size_t {
718 SpeedscopeFrame fieldSpeedscopeFrame;
719 fieldSpeedscopeFrame.fString =
720 tupleDescriptor.GetQualifiedFieldName(fieldDescriptor.GetId()) +
" (" + fieldDescriptor.GetTypeName() +
")";
721 fieldSpeedscopeFrame.fOpeningPosition = positionCursor;
722 frames.push_back(fieldSpeedscopeFrame);
724 std::size_t fieldSpeedscopeFrameIndex = frames.size() - 1;
726 std::size_t subTreeSize = 0;
727 const auto &childIds = fieldDescriptor.GetLinkIds();
729 for (
const auto &childFieldId : childIds) {
730 const auto &childFieldDescriptor = tupleDescriptor.GetFieldDescriptor(childFieldId);
731 subTreeSize += self(self, childFieldDescriptor);
734 for (
const auto &columnDescriptor : tupleDescriptor.GetColumnIterable(fieldDescriptor.GetId())) {
735 const auto &columnInfo = GetColumnInspector(columnDescriptor.GetPhysicalId());
736 std::size_t columnSize = columnInfo.GetCompressedSize();
738 SpeedscopeFrame columnSpeedscopeFrame;
739 columnSpeedscopeFrame.fString =
740 "[col#" + std::to_string(columnDescriptor.GetPhysicalId()) +
"] " +
741 tupleDescriptor.GetQualifiedFieldName(fieldDescriptor.GetId()) +
" (" +
743 columnSpeedscopeFrame.fOpeningPosition = positionCursor;
744 positionCursor += columnSize;
745 columnSpeedscopeFrame.fClosingPosition = positionCursor;
746 frames.push_back(columnSpeedscopeFrame);
747 subTreeSize += columnSize;
750 frames[fieldSpeedscopeFrameIndex].fClosingPosition = positionCursor;
755 const auto &topLevelIds = rootFieldDescriptor.GetLinkIds();
756 for (
const auto &childId : topLevelIds) {
757 const auto &childFieldDescriptor = tupleDescriptor.GetFieldDescriptor(childId);
758 visitFieldsRecursive(visitFieldsRecursive, childFieldDescriptor);
761 PrintSpeedscopeFrames(frames, output);
773 throw RException(
R__FAIL(
"Disk profile is only supported for file-based page sources"));
778 const auto &descriptor = GetDescriptor();
780 struct RDiskPageLeaf {
781 std::uint64_t fPosition = 0;
782 std::uint64_t
fSize = 0;
784 std::array<DescriptorId_t, 3> fAncestors;
786 static constexpr std::array<const char *, 3> kAncestorsNames = {
"cluster group",
"cluster",
"column range"};
787 std::vector<RDiskPageLeaf> pageLeaves;
790 for (
const auto &clusterGroupDescriptor : descriptor.GetClusterGroupIterable()) {
791 const auto groupId = clusterGroupDescriptor.GetId();
793 for (
const auto clusterId : clusterGroupDescriptor.GetClusterIds()) {
794 const auto &clusterDescriptor = descriptor.GetClusterDescriptor(clusterId);
796 for (
const auto &columnRange : clusterDescriptor.GetColumnRangeIterable()) {
797 const auto columnId = columnRange.GetPhysicalColumnId();
799 const auto &pageRange = clusterDescriptor.GetPageRange(columnId);
800 for (
const auto &pageInfo : pageRange.GetPageInfos()) {
801 const auto &locator = pageInfo.GetLocator();
803 RDiskPageLeaf pageLeaf;
804 pageLeaf.fPosition = locator.GetPosition<std::uint64_t>();
805 pageLeaf.fSize = locator.GetNBytesOnStorage() +
807 pageLeaf.fName =
"[page @" + std::to_string(pageLeaf.fPosition) +
"]";
808 pageLeaf.fAncestors = {groupId, clusterId, columnId};
809 pageLeaves.push_back(pageLeaf);
816 std::sort(pageLeaves.begin(), pageLeaves.end(),
817 [](
const RDiskPageLeaf &
a,
const RDiskPageLeaf &
b) { return a.fPosition < b.fPosition; });
821 std::unique(pageLeaves.begin(), pageLeaves.end(),
822 [](
const RDiskPageLeaf &
a,
const RDiskPageLeaf &
b) { return a.fPosition == b.fPosition; }),
825 std::vector<SpeedscopeFrame> frames;
829 SpeedscopeFrame headerFrame;
830 headerFrame.fString =
"ntuple header";
831 headerFrame.fOpeningPosition = anchor->GetSeekHeader();
832 headerFrame.fClosingPosition = anchor->GetSeekHeader() + anchor->GetNBytesHeader();
833 frames.push_back(headerFrame);
838 std::size_t fIndex = 0;
840 std::vector<ROpenFrame> openFrames;
841 std::uint64_t previouspageLeafEnd = 0;
844 for (
const auto &pageLeaf : pageLeaves) {
845 std::size_t sharedDepth = 0;
848 while (sharedDepth < openFrames.size() && sharedDepth < pageLeaf.fAncestors.size() &&
849 openFrames[sharedDepth].fId == pageLeaf.fAncestors[sharedDepth]) {
854 while (openFrames.size() > sharedDepth) {
855 frames[openFrames.back().fIndex].fClosingPosition = previouspageLeafEnd;
856 openFrames.pop_back();
860 for (std::size_t depth = sharedDepth; depth < pageLeaf.fAncestors.size(); ++depth) {
861 SpeedscopeFrame ancestorFrame;
862 ancestorFrame.fString =
863 "[" + std::string(kAncestorsNames[depth]) +
" " + std::to_string(pageLeaf.fAncestors[depth]) +
"]";
864 ancestorFrame.fOpeningPosition = pageLeaf.fPosition;
865 frames.push_back(ancestorFrame);
867 ROpenFrame openFrame;
868 openFrame.fId = pageLeaf.fAncestors[depth];
869 openFrame.fIndex = frames.size() - 1;
870 openFrames.push_back(openFrame);
874 SpeedscopeFrame pageLeafFrame;
875 pageLeafFrame.fString = pageLeaf.fName;
876 pageLeafFrame.fOpeningPosition = pageLeaf.fPosition;
877 pageLeafFrame.fClosingPosition = pageLeaf.fPosition + pageLeaf.fSize;
878 frames.push_back(pageLeafFrame);
880 previouspageLeafEnd = pageLeaf.fPosition + pageLeaf.fSize;
884 while (!openFrames.empty()) {
885 frames[openFrames.back().fIndex].fClosingPosition = previouspageLeafEnd;
886 openFrames.pop_back();
890 for (
const auto &clusterGroupDescriptor : descriptor.GetClusterGroupIterable()) {
891 const auto locator = clusterGroupDescriptor.GetPageListLocator();
893 SpeedscopeFrame pageListFrame;
894 pageListFrame.fString =
"[page list " + std::to_string(clusterGroupDescriptor.GetId()) +
"]";
895 pageListFrame.fOpeningPosition = locator.GetPosition<std::uint64_t>();
896 pageListFrame.fClosingPosition = locator.GetPosition<std::uint64_t>() + locator.GetNBytesOnStorage();
897 frames.push_back(pageListFrame);
902 SpeedscopeFrame footerFrame;
903 footerFrame.fString =
"ntuple footer";
904 footerFrame.fOpeningPosition = anchor->GetSeekFooter();
905 footerFrame.fClosingPosition = anchor->GetSeekFooter() + anchor->GetNBytesFooter();
906 frames.push_back(footerFrame);
909 PrintSpeedscopeFrames(frames, output);
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
#define R__LOG_WARNING(...)
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t format
std::string & operator+=(std::string &left, const TString &right)
The available trivial, native content types of a column.
Provides column-level storage information.
std::uint64_t GetCompressedSize() const
std::uint64_t GetUncompressedSize() const
std::uint64_t GetNPages() const
std::uint64_t GetNElements() const
Provides field-level storage information.
Inspect on-disk and storage-related information of an RNTuple.
std::vector< ROOT::DescriptorId_t > GetFieldsByName(const std::regex &fieldNamePattern, bool searchInSubfields=true) const
Get the IDs of (sub-)fields whose name matches the given string.
const RFieldTreeInspector & GetFieldTreeInspector(ROOT::DescriptorId_t fieldId) const
Get storage information for a given (sub)field by ID.
std::unique_ptr< TH1D > GetPageSizeDistribution(ROOT::DescriptorId_t physicalColumnId, std::string histName="", std::string histTitle="", size_t nBins=64)
Get a histogram containing the size distribution of the compressed pages for an individual column.
size_t GetColumnCountByType(ROOT::ENTupleColumnType colType) const
Get the number of columns of a given type present in the RNTuple.
std::vector< ROOT::ENTupleColumnType > GetColumnTypes()
Get all column types present in the RNTuple being inspected.
size_t GetFieldCountByType(const std::regex &typeNamePattern, bool searchInSubfields=true) const
Get the number of fields of a given type or class present in the RNTuple.
void PrintSchemaProfile(std::ostream &output=std::cout, ESchemaProfileFormat format=ESchemaProfileFormat::kSpeedscopeJSON) const
Print a string that represents the tree of the (sub)fields and columns of an RNTuple in a format whic...
std::vector< ROOT::DescriptorId_t > GetColumnsByType(ROOT::ENTupleColumnType colType)
Get the IDs of all columns with the given type.
std::string GetCompressionSettingsAsString() const
Get a string describing compression settings of the RNTuple being inspected.
RFieldTreeInspector CollectFieldTreeInfo(ROOT::DescriptorId_t fieldId)
Recursively gather field-level information.
RNTupleInspector(std::unique_ptr< ROOT::Internal::RPageSource > pageSource)
void PrintColumnTypeInfo(ENTupleInspectorPrintFormat format=ENTupleInspectorPrintFormat::kTable, std::ostream &output=std::cout)
Print storage information per column type.
std::unique_ptr< THStack > GetPagesPerClusterDistribution(std::initializer_list< ROOT::ENTupleColumnType > colTypes={}, std::string_view histName="", std::string_view histTitle="", size_t nBins=32)
void PrintDiskProfile(std::ostream &output=std::cout, ESchemaProfileFormat format=ESchemaProfileFormat::kSpeedscopeJSON) const
Print a string that represents the on-disk storage of the cluster groups, clusters,...
const RColumnInspector & GetColumnInspector(ROOT::DescriptorId_t physicalColumnId) const
Get storage information for a given column.
std::unique_ptr< ROOT::Internal::RPageSource > fPageSource
static std::unique_ptr< RNTupleInspector > Create(const RNTuple &sourceNTuple)
Create a new RNTupleInspector.
void CollectColumnInfo()
Gather column-level and RNTuple-level information.
void PrintFieldTreeAsDot(const ROOT::RFieldDescriptor &fieldDescriptor, std::ostream &output=std::cout) const
Print a .dot string that represents the tree of the (sub)fields of an RNTuple.
std::vector< ROOT::DescriptorId_t > GetAllColumnsOfField(ROOT::DescriptorId_t fieldId) const
Get the columns that make up the given field, including its subfields.
std::unique_ptr< TH1D > GetColumnTypeInfoAsHist(ENTupleInspectorHist histKind, std::string_view histName="", std::string_view histTitle="")
Get a histogram showing information for each column type present,.
ROOT::RNTupleDescriptor fDescriptor
A column element encapsulates the translation between basic C++ types and their column representation...
static const char * GetColumnTypeName(ROOT::ENTupleColumnType type)
static std::unique_ptr< RColumnElementBase > Generate(ROOT::ENTupleColumnType type)
If CppT == void, use the default C++ type for the given column type.
Storage provider that reads ntuple pages from a file.
static std::unique_ptr< RPageSourceFile > CreateFromAnchor(const RNTuple &anchor, const ROOT::RNTupleReadOptions &options=ROOT::RNTupleReadOptions())
Used from the RNTuple class to build a datasource if the anchor is already available.
static std::unique_ptr< RPageSource > Create(std::string_view ntupleName, std::string_view location, const ROOT::RNTupleReadOptions &options=ROOT::RNTupleReadOptions())
Guess the concrete derived page source from the file name (location)
static constexpr std::size_t kNBytesPageChecksum
The page checksum is a 64bit xxhash3.
Base class for all ROOT issued exceptions.
Metadata stored for every field of an RNTuple.
ROOT::DescriptorId_t GetId() const
std::uint32_t GetFieldVersion() const
const std::vector< ROOT::DescriptorId_t > & GetLinkIds() const
ROOT::DescriptorId_t GetParentId() const
const std::string & GetFieldDescription() const
const std::string & GetFieldName() const
const std::string & GetTypeName() const
ROOT::NTupleSize_t R__DEPRECATED(6, 46, "This function is ill-conceived in the descriptor " "as not all cluster descriptors may be present. This interface is no longer publicly exposed.") GetNElements(ROOT ROOT::DescriptorId_t GetFieldZeroId() const
Returns the logical parent of all top-level RNTuple data fields.
RNTupleDescriptor Clone() const
Representation of an RNTuple data set in a ROOT file.
1-D histogram with a double per channel (see TH1 documentation)
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
@ kSpeedscopeJSON
https://www.speedscope.app/file-format-schema.json
ENTupleInspectorPrintFormat
ROOT::RLogChannel & NTupleLog()
Log channel for RNTuple diagnostics.
const ROOT::RNTuple * GetAnchorFromFile(const RPageSourceFile &source)
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
constexpr DescriptorId_t kInvalidDescriptorId
EValues
Note: this is only temporarily a struct and will become a enum class hence the name convention used.
static std::string AlgorithmToString(EAlgorithm::EValues algorithm)