This is an automated email from the ASF dual-hosted git repository.

apitrou pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/master by this push:
     new 4bc9355020 PARQUET-2204: [parquet-cpp] TypedColumnReaderImpl::Skip 
should reuse scratch space (#14509)
4bc9355020 is described below

commit 4bc935502065b490b6be1d3201fb3e134a92dcb3
Author: Fatemah Panahi <[email protected]>
AuthorDate: Thu Dec 8 07:42:00 2022 -0800

    PARQUET-2204: [parquet-cpp] TypedColumnReaderImpl::Skip should reuse 
scratch space (#14509)
    
    TypedColumnReaderImpl::Skip allocates scratch space on every call. The 
scratch space is used to read rep/def levels and values and throw them away. 
The memory allocation slows down the skip based on microbenchmarks. The scratch 
space can be allocated once and re-used.
    
    
    
    Lead-authored-by: Fatemah Panahi <[email protected]>
    Co-authored-by: Fatemah Panahi <[email protected]>
    Signed-off-by: Antoine Pitrou <[email protected]>
---
 cpp/src/parquet/column_reader.cc | 58 ++++++++++++++++++++++++----------------
 1 file changed, 35 insertions(+), 23 deletions(-)

diff --git a/cpp/src/parquet/column_reader.cc b/cpp/src/parquet/column_reader.cc
index cab9bb0fb3..dc98041d3a 100644
--- a/cpp/src/parquet/column_reader.cc
+++ b/cpp/src/parquet/column_reader.cc
@@ -68,6 +68,10 @@ namespace {
 // better vectorized performance when doing many smaller record reads
 constexpr int64_t kMinLevelBatchSize = 1024;
 
+// Batch size for reading and throwing away values during skip.
+// Both RecordReader and the ColumnReader use this for skipping.
+constexpr int64_t kSkipScratchBatchSize = 1024;
+
 inline bool HasSpacedValues(const ColumnDescriptor* descr) {
   if (descr->max_repetition_level() > 0) {
     // repeated+flat case
@@ -941,6 +945,14 @@ class TypedColumnReaderImpl : public 
TypedColumnReader<DType>,
     this->exposed_encoding_ = encoding;
   }
 
+  // Allocate enough scratch space to accommodate skipping 16-bit levels or any
+  // value type.
+  void InitScratchForSkip();
+
+  // Scratch space for reading and throwing away rep/def levels and values when
+  // skipping.
+  std::shared_ptr<ResizableBuffer> scratch_for_skip_;
+
  private:
   // Read dictionary indices. Similar to ReadValues but decode data to 
dictionary indices.
   // This function is called only by ReadBatchWithDictionary().
@@ -1151,6 +1163,15 @@ int64_t TypedColumnReaderImpl<DType>::ReadBatchSpaced(
   return total_values;
 }
 
+template <typename DType>
+void TypedColumnReaderImpl<DType>::InitScratchForSkip() {
+  if (this->scratch_for_skip_ == nullptr) {
+    int value_size = type_traits<DType::type_num>::value_byte_size;
+    this->scratch_for_skip_ = AllocateBuffer(
+        this->pool_, kSkipScratchBatchSize * std::max<int>(sizeof(int16_t), 
value_size));
+  }
+}
+
 template <typename DType>
 int64_t TypedColumnReaderImpl<DType>::Skip(int64_t num_values_to_skip) {
   int64_t values_to_skip = num_values_to_skip;
@@ -1165,23 +1186,16 @@ int64_t TypedColumnReaderImpl<DType>::Skip(int64_t 
num_values_to_skip) {
     } else {
       // We need to read this Page
       // Jump to the right offset in the Page
-      int64_t batch_size =
-          kMinLevelBatchSize;  // ReadBatch with a smaller memory footprint
       int64_t values_read = 0;
-
-      // This will be enough scratch space to accommodate 16-bit levels or any
-      // value type
-      int value_size = type_traits<DType::type_num>::value_byte_size;
-      std::shared_ptr<ResizableBuffer> scratch = AllocateBuffer(
-          this->pool_, batch_size * std::max<int>(sizeof(int16_t), 
value_size));
-
+      InitScratchForSkip();
+      ARROW_DCHECK_NE(this->scratch_for_skip_, nullptr);
       do {
-        batch_size = std::min(batch_size, values_to_skip);
-        values_read =
-            ReadBatch(static_cast<int>(batch_size),
-                      reinterpret_cast<int16_t*>(scratch->mutable_data()),
-                      reinterpret_cast<int16_t*>(scratch->mutable_data()),
-                      reinterpret_cast<T*>(scratch->mutable_data()), 
&values_read);
+        int64_t batch_size = std::min(kSkipScratchBatchSize, values_to_skip);
+        values_read = ReadBatch(
+            static_cast<int>(batch_size),
+            
reinterpret_cast<int16_t*>(this->scratch_for_skip_->mutable_data()),
+            
reinterpret_cast<int16_t*>(this->scratch_for_skip_->mutable_data()),
+            reinterpret_cast<T*>(this->scratch_for_skip_->mutable_data()), 
&values_read);
         values_to_skip -= values_read;
       } while (values_read > 0 && values_to_skip > 0);
     }
@@ -1517,18 +1531,16 @@ class TypedRecordReader : public 
TypedColumnReaderImpl<DType>,
   // Throws an error if it could not read 'num_values'.
   void ReadAndThrowAwayValues(int64_t num_values) {
     int64_t values_left = num_values;
-    int64_t batch_size = kMinLevelBatchSize;  // ReadBatch with a smaller 
memory footprint
     int64_t values_read = 0;
 
-    // This will be enough scratch space to accommodate 16-bit levels or any
+    // Allocate enough scratch space to accommodate 16-bit levels or any
     // value type
-    int value_size = type_traits<DType::type_num>::value_byte_size;
-    std::shared_ptr<ResizableBuffer> scratch = AllocateBuffer(
-        this->pool_, batch_size * std::max<int>(sizeof(int16_t), value_size));
+    this->InitScratchForSkip();
+    ARROW_DCHECK_NE(this->scratch_for_skip_, nullptr);
     do {
-      batch_size = std::min<int64_t>(batch_size, values_left);
-      values_read =
-          this->ReadValues(batch_size, 
reinterpret_cast<T*>(scratch->mutable_data()));
+      int64_t batch_size = std::min<int64_t>(kSkipScratchBatchSize, 
values_left);
+      values_read = this->ReadValues(
+          batch_size, 
reinterpret_cast<T*>(this->scratch_for_skip_->mutable_data()));
       values_left -= values_read;
     } while (values_read > 0 && values_left > 0);
     if (values_left > 0) {

Reply via email to