-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Compact run buffer slice values #10292
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -277,9 +277,28 @@ where | |
| logical_offset.saturating_add(logical_length) <= self.logical_length, | ||
| "the length + offset of the sliced RunEndBuffer cannot exceed the existing length" | ||
| ); | ||
| Self { | ||
| let logical_offset = self.logical_offset + logical_offset; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cc @Rich-T-kid this is what i was thinking on my previous comments on your PR essentially we can still reduce how many physical values we hold on to, without needing to readjust all of the values (still keeping it zero-copy) we'd need to extend it to runarray too since need to ensure the values array is similarly compacted (might need a bit of plumbing to make it work) and as noted in the issue callsites may need to be adjusted lemme know your thoughts |
||
|
|
||
| if logical_length == 0 { | ||
| return Self { | ||
| run_ends: self.run_ends.slice(0, 0), | ||
| logical_length: 0, | ||
| logical_offset: 0, | ||
| }; | ||
| } | ||
|
|
||
| // tmp makes it easier to use the get physical index methods here | ||
| let tmp = Self { | ||
| run_ends: self.run_ends.clone(), | ||
| logical_offset: self.logical_offset + logical_offset, | ||
| logical_offset, | ||
| logical_length, | ||
| }; | ||
| let start = tmp.get_start_physical_index(); | ||
| let end = tmp.get_end_physical_index(); | ||
|
|
||
| Self { | ||
| run_ends: self.run_ends.slice(start, end - start + 1), | ||
| logical_offset, | ||
| logical_length, | ||
| } | ||
| } | ||
|
|
@@ -421,4 +440,53 @@ mod tests { | |
| let sliced_values: Vec<i32> = sliced.sliced_values().collect(); | ||
| assert_eq!(sliced_values, &[2]); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_compact_slicing() { | ||
| // {} represents a logical slice within physically expanded [] | ||
| // [{A, A, A, A, B, B, B, B, C, C, C, C}] | ||
| let buffer = RunEndBuffer::<i32>::new(vec![4, 8, 12].into(), 0, 12); | ||
|
|
||
| // zero slice | ||
| let slice = buffer.slice(2, 0); | ||
| assert_eq!(slice.len(), 0); | ||
| assert_eq!(slice.offset(), 0); | ||
| assert!(slice.values().is_empty()); | ||
|
|
||
| // compact start only | ||
| // [B, B, B, B, B, B, {B, B, C, C, C, C}] | ||
| let slice = buffer.slice(6, 6); | ||
| assert_eq!(slice.len(), 6); | ||
| assert_eq!(slice.offset(), 6); | ||
|
Comment on lines
+457
to
+460
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i realized my initial version of the PR incorrectly adjusted the offset when that wasnt needed; by removing the first physical value its as if the first run was consumed by the following run since we always list run lengths; that is
|
||
| assert_eq!(slice.values(), &[8, 12]); | ||
| let values = slice.sliced_values().collect::<Vec<_>>(); | ||
| assert_eq!(values, &[2, 6]); | ||
|
|
||
| // compact end only | ||
| // [A, {A, A, A, B, B, B}, B] | ||
| let slice = buffer.slice(1, 6); | ||
| assert_eq!(slice.len(), 6); | ||
| assert_eq!(slice.offset(), 1); | ||
| assert_eq!(slice.values(), &[4, 8]); | ||
| let values = slice.sliced_values().collect::<Vec<_>>(); | ||
| assert_eq!(values, &[3, 6]); | ||
|
|
||
| // compact both | ||
| // [B, B, B, B, B, {B, B}, B] | ||
| let slice = buffer.slice(5, 2); | ||
| assert_eq!(slice.len(), 2); | ||
| assert_eq!(slice.offset(), 5); | ||
| assert_eq!(slice.values(), &[8]); | ||
| let values = slice.sliced_values().collect::<Vec<_>>(); | ||
| assert_eq!(values, &[2]); | ||
|
|
||
| // no compaction | ||
| // [A, {A, A, A, B, B, B, B, C, C, C}, C] | ||
| let slice = buffer.slice(1, 10); | ||
| assert_eq!(slice.len(), 10); | ||
| assert_eq!(slice.offset(), 1); | ||
| assert_eq!(slice.values(), &[4, 8, 12]); | ||
| let values = slice.sliced_values().collect::<Vec<_>>(); | ||
| assert_eq!(values, &[3, 7, 10]); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can reference this test to see how the physical values change underneath as we slice