diff --git a/dwio/nimble/tablet/TabletReader.cpp b/dwio/nimble/tablet/TabletReader.cpp index 87c58f12..f7d014e4 100644 --- a/dwio/nimble/tablet/TabletReader.cpp +++ b/dwio/nimble/tablet/TabletReader.cpp @@ -373,6 +373,9 @@ void TabletReader::loadFooter( footerOffset, footerBuf->size(), footerBuf->asMutable()); + } else { + stats_.footerBufferOverread = + static_cast(footerIoSize - requiredSize); } const uint64_t footerOffset = diff --git a/dwio/nimble/tablet/TabletReader.h b/dwio/nimble/tablet/TabletReader.h index dbbef9f0..7874e0bc 100644 --- a/dwio/nimble/tablet/TabletReader.h +++ b/dwio/nimble/tablet/TabletReader.h @@ -303,6 +303,17 @@ class TabletReader { return ps_.footerSize(); } + /// TabletReader-level statistics collected during file open. + struct Stats { + /// Bytes read beyond the footer + postscript in speculative mode. + /// Zero in adaptive mode (exact-size read). + int64_t footerBufferOverread{0}; + }; + + const Stats& stats() const { + return stats_; + } + CompressionType footerCompressionType() const { return ps_.footerCompressionType(); } @@ -525,6 +536,7 @@ class TabletReader { const std::unique_ptr metadataInput_; uint64_t fileSize_{0}; + Stats stats_; Postscript ps_; std::unique_ptr footer_; std::unique_ptr stripes_; diff --git a/dwio/nimble/tablet/tests/TabletTest.cpp b/dwio/nimble/tablet/tests/TabletTest.cpp index fc09c68b..3d272012 100644 --- a/dwio/nimble/tablet/tests/TabletTest.cpp +++ b/dwio/nimble/tablet/tests/TabletTest.cpp @@ -4406,6 +4406,8 @@ TEST_P(TabletTest, readerOptionsAdaptiveMode) { EXPECT_EQ(tablet->stripeCount(), 1); EXPECT_EQ(tablet->stripeRowCount(0), 500); + // Adaptive mode reads the exact footer size, so no bytes are wasted. + EXPECT_EQ(tablet->stats().footerBufferOverread, 0); } TEST_P(TabletTest, readerOptionsSpeculativeMode) { @@ -4438,6 +4440,11 @@ TEST_P(TabletTest, readerOptionsSpeculativeMode) { EXPECT_EQ(tablet->stripeCount(), 1); EXPECT_EQ(tablet->stripeRowCount(0), 600); + // Speculative mode reads more than needed; overread is the wasted bytes. + const auto footerRequired = tablet->footerSize() + nimble::kPostscriptSize; + EXPECT_EQ( + tablet->stats().footerBufferOverread, + std::min(1024, file.size()) - footerRequired); } TEST_P(TabletTest, configureOptionsIndexFlags) { diff --git a/dwio/nimble/velox/selective/SelectiveNimbleReader.cpp b/dwio/nimble/velox/selective/SelectiveNimbleReader.cpp index 1563c0b0..b64441bc 100644 --- a/dwio/nimble/velox/selective/SelectiveNimbleReader.cpp +++ b/dwio/nimble/velox/selective/SelectiveNimbleReader.cpp @@ -328,6 +328,8 @@ uint64_t SelectiveNimbleRowReader::next( void SelectiveNimbleRowReader::updateRuntimeStats( dwio::common::RuntimeStatistics& stats) const { stats.skippedStrides += skippedStripes_; + stats.footerBufferOverread += + readerBase_->tablet().stats().footerBufferOverread; stats.columnReaderStats.mergeFrom(columnReaderStatistics_); }