adriangb commented on code in PR #11235:
URL: https://github.com/apache/arrow-rs/pull/11235#discussion_r4214518940


##########
parquet/src/arrow/push_decoder/mod.rs:
##########
@@ -527,6 +535,21 @@ impl ParquetPushDecoder {
     /// Note this can be the entire file or just a part of it. If it is part 
of the file,
     /// the ranges should correspond to the data ranges requested by the 
decoder.
     ///
+    /// When the decoder is done with a row group that it reads, it releases

Review Comment:
   Fixed in 
https://github.com/apache/arrow-rs/pull/11235/commits/14c209bd03863a0020d152f6e380fcba32fa6ae4



##########
parquet/src/arrow/push_decoder/mod.rs:
##########
@@ -527,6 +535,21 @@ impl ParquetPushDecoder {
     /// Note this can be the entire file or just a part of it. If it is part 
of the file,
     /// the ranges should correspond to the data ranges requested by the 
decoder.
     ///
+    /// When the decoder is done with a row group that it reads, it releases
+    /// the pushed bytes of all column chunks of that row group, unless the

Review Comment:
   Fixed in 
https://github.com/apache/arrow-rs/pull/11235/commits/14c209bd03863a0020d152f6e380fcba32fa6ae4



##########
parquet/src/arrow/push_decoder/mod.rs:
##########
@@ -527,6 +535,21 @@ impl ParquetPushDecoder {
     /// Note this can be the entire file or just a part of it. If it is part 
of the file,
     /// the ranges should correspond to the data ranges requested by the 
decoder.
     ///
+    /// When the decoder is done with a row group that it reads, it releases
+    /// the pushed bytes of all column chunks of that row group, unless the
+    /// scan reads the row group again. This is also true for bytes that the

Review Comment:
   Fixed in 
https://github.com/apache/arrow-rs/pull/11235/commits/14c209bd03863a0020d152f6e380fcba32fa6ae4



##########
parquet/src/arrow/push_decoder/mod.rs:
##########
@@ -527,6 +535,21 @@ impl ParquetPushDecoder {
     /// Note this can be the entire file or just a part of it. If it is part 
of the file,
     /// the ranges should correspond to the data ranges requested by the 
decoder.
     ///
+    /// When the decoder is done with a row group that it reads, it releases
+    /// the pushed bytes of all column chunks of that row group, unless the
+    /// scan reads the row group again. This is also true for bytes that the
+    /// decoder did not request, and for bytes in a buffer that is larger than
+    /// a requested range. The decoder does not release the bytes of row
+    /// groups that it does not read (for example, row groups without selected
+    /// rows, or after the limit). Call [`Self::clear_all_ranges`] to release
+    /// them.
+    ///
+    /// Releasing bytes decreases [`Self::buffered_bytes`], but the memory of
+    /// a pushed [`Bytes`] is freed only after all zero-copy slices of it are

Review Comment:
   Fixed in 
https://github.com/apache/arrow-rs/pull/11235/commits/14c209bd03863a0020d152f6e380fcba32fa6ae4



##########
parquet/src/arrow/push_decoder/mod.rs:
##########
@@ -666,9 +689,10 @@ impl ParquetPushDecoder {
     ///
     /// The decoder's buffered bytes are carried across the rebuild: bytes
     /// already fetched for row groups the new configuration still reads are
-    /// not re-requested. Bytes the new configuration no longer needs stay
-    /// buffered until [`clear_all_ranges`](Self::clear_all_ranges) is called
-    /// or the rebuilt decoder is dropped.
+    /// not re-requested. [`build`](ParquetPushDecoderBuilder::build) releases
+    /// the bytes that the new configuration does not read: the bytes outside

Review Comment:
   Fixed in 
https://github.com/apache/arrow-rs/pull/11235/commits/14c209bd03863a0020d152f6e380fcba32fa6ae4



##########
parquet/src/util/push_buffers.rs:
##########
@@ -180,15 +185,156 @@ impl PushBuffers {
                 new_buffers.push(buffer.clone());
             }
         }
+        self.buffered_bytes = new_ranges.iter().map(|r| r.end - r.start).sum();
         self.ranges = new_ranges;
         self.buffers = new_buffers;
     }
 
+    /// Remove all buffered bytes in `ranges`, whatever the shape of the

Review Comment:
   Fixed in 
https://github.com/apache/arrow-rs/pull/11235/commits/14c209bd03863a0020d152f6e380fcba32fa6ae4



##########
parquet/src/util/push_buffers.rs:
##########
@@ -286,4 +552,137 @@ mod tests {
             "Parquet error: Number of ranges (2) must match number of buffers 
(1)"
         );
     }
+
+    /// The result of `release_ranges`, computed by rebuilding all buffers.
+    #[cfg(feature = "arrow")]
+    fn release_by_rebuild(
+        buffers: &PushBuffers,
+        release: &[Range<u64>],
+    ) -> Vec<(Range<u64>, Bytes)> {
+        let release = merge_ranges(release);
+        let mut parts = vec![];
+        for (range, buffer) in buffers.iter() {
+            let mut start = range.start;
+            let mut keep = |part: Range<u64>| {
+                let offset = |pos: u64| (pos - range.start) as usize;
+                parts.push((
+                    part.clone(),
+                    buffer.slice(offset(part.start)..offset(part.end)),
+                ));
+            };
+            for r in release
+                .iter()
+                .filter(|r| r.start < range.end && r.end > range.start)
+            {
+                if start < r.start {
+                    keep(start..r.start);
+                }
+                start = start.max(r.end);
+            }
+            if start < range.end {
+                keep(start..range.end);
+            }
+        }
+        parts.sort_by_key(|(range, _)| range.start);
+        parts
+    }
+
+    #[test]
+    #[cfg(feature = "arrow")]
+    #[expect(clippy::reversed_empty_ranges)]
+    fn release_ranges_splits_and_removes_empty_buffers() {
+        let mut buffers = PushBuffers::new(100);
+        buffers
+            .push_range(0..20, Bytes::from_static(b"abcdefghijklmnopqrst"))
+            .unwrap();
+        // An empty and an inverted range, which `push_range` accepts.
+        buffers.push_range(30..30, Bytes::new()).unwrap();
+        buffers.push_range(10..5, Bytes::new()).unwrap();
+
+        // Split one buffer into three parts.
+        buffers.release_ranges(&[3..5, 8..10]);
+        assert_eq!(buffers.ranges, vec![0..3, 5..8, 10..20]);
+        assert_eq!(buffers.buffered_bytes(), 16);
+        assert_eq!(buffers.get_bytes(5, 3).unwrap(), 
Bytes::from_static(b"fgh"));
+
+        // Release a whole buffer.
+        release(&mut buffers, 5..8);
+        assert_eq!(buffers.ranges, vec![0..3, 10..20]);
+        assert_eq!(buffers.buffered_bytes(), 13);
+    }
+
+    #[test]
+    #[cfg(feature = "arrow")]
+    fn release_ranges_matches_rebuild() {

Review Comment:
   Fixed in 
https://github.com/apache/arrow-rs/pull/11235/commits/14c209bd03863a0020d152f6e380fcba32fa6ae4



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to