-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Remove custom doubling strategy + add examples to VecAllocEx
#9058
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
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 |
|---|---|---|
|
|
@@ -28,6 +28,35 @@ pub trait VecAllocExt { | |
| /// `accounting` by any newly allocated bytes. | ||
| /// | ||
| /// Note that allocation counts capacity, not size | ||
| /// | ||
| /// # Example: | ||
| /// ``` | ||
| /// # use datafusion_execution::memory_pool::proxy::VecAllocExt; | ||
| /// // use allocated to incrementally track how much memory is allocated in the vec | ||
| /// let mut allocated = 0; | ||
| /// let mut vec = Vec::new(); | ||
| /// // Push data into the vec and the accounting will be updated to reflect | ||
| /// // memory allocation | ||
| /// vec.push_accounted(1, &mut allocated); | ||
| /// assert_eq!(allocated, 16); // space for 4 u32s | ||
| /// vec.push_accounted(1, &mut allocated); | ||
| /// assert_eq!(allocated, 16); // no new allocation needed | ||
| /// | ||
| /// // push more data into the vec | ||
| /// for _ in 0..10 { vec.push_accounted(1, &mut allocated); } | ||
| /// assert_eq!(allocated, 64); // underlying vec has space for 10 u32s | ||
| /// assert_eq!(vec.allocated_size(), 64); | ||
| /// ``` | ||
| /// # Example with other allocations: | ||
| /// ``` | ||
| /// # use datafusion_execution::memory_pool::proxy::VecAllocExt; | ||
| /// // You can use the same allocated size to track memory allocated by | ||
| /// // another source. For example | ||
| /// let mut allocated = 27; | ||
| /// let mut vec = Vec::new(); | ||
| /// vec.push_accounted(1, &mut allocated); // allocates 16 bytes for vec | ||
| /// assert_eq!(allocated, 43); // 16 bytes for vec, 27 bytes for other | ||
| /// ``` | ||
| fn push_accounted(&mut self, x: Self::T, accounting: &mut usize); | ||
|
|
||
| /// Return the amount of memory allocated by this Vec to store elements | ||
|
|
@@ -36,24 +65,41 @@ pub trait VecAllocExt { | |
| /// Note this calculation is not recursive, and does not include any heap | ||
| /// allocations contained within the Vec's elements. Does not include the | ||
| /// size of `self` | ||
| /// | ||
| /// # Example: | ||
| /// ``` | ||
| /// # use datafusion_execution::memory_pool::proxy::VecAllocExt; | ||
| /// let mut vec = Vec::new(); | ||
| /// // Push data into the vec and the accounting will be updated to reflect | ||
| /// // memory allocation | ||
| /// vec.push(1); | ||
| /// assert_eq!(vec.allocated_size(), 16); // space for 4 u32s | ||
| /// vec.push(1); | ||
| /// assert_eq!(vec.allocated_size(), 16); // no new allocation needed | ||
| /// | ||
| /// // push more data into the vec | ||
| /// for _ in 0..10 { vec.push(1); } | ||
| /// assert_eq!(vec.allocated_size(), 64); // space for 64 now | ||
| /// ``` | ||
| fn allocated_size(&self) -> usize; | ||
| } | ||
|
|
||
| impl<T> VecAllocExt for Vec<T> { | ||
| type T = T; | ||
|
|
||
| fn push_accounted(&mut self, x: Self::T, accounting: &mut usize) { | ||
| if self.capacity() == self.len() { | ||
| // allocate more | ||
|
|
||
| // growth factor: 2, but at least 2 elements | ||
| let bump_elements = (self.capacity() * 2).max(2); | ||
| let bump_size = std::mem::size_of::<u32>() * bump_elements; | ||
|
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 think this should be
Contributor
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. looks correct. I suspect this was the cause of the discrepancy in the original code |
||
| self.reserve(bump_elements); | ||
| let prev_capacty = self.capacity(); | ||
| self.push(x); | ||
| let new_capacity = self.capacity(); | ||
| if new_capacity > prev_capacty { | ||
| // capacity changed, so we allocated more | ||
| let bump_size = (new_capacity - prev_capacty) * std::mem::size_of::<T>(); | ||
|
Contributor
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. does it make sense to do a
Contributor
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. either that or remove the
Contributor
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. thinking about it more: if
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 think that is a good point. I will add a comment to clarify |
||
| // Note multiplication should never overflow because `push` would | ||
| // have panic'd first, but the checked_add could potentially | ||
| // overflow since accounting could be tracking additional values, and | ||
| // could be greater than what is stored in the Vec | ||
| *accounting = (*accounting).checked_add(bump_size).expect("overflow"); | ||
| } | ||
|
|
||
| self.push(x); | ||
| } | ||
| fn allocated_size(&self) -> usize { | ||
| std::mem::size_of::<T>() * self.capacity() | ||
|
|
@@ -69,7 +115,7 @@ pub trait RawTableAllocExt { | |
| /// `accounting` by any newly allocated bytes. | ||
| /// | ||
| /// Returns the bucket where the element was inserted. | ||
| /// Note that allocation counts capacity, not size. | ||
| /// Note that allocation counts capacity, not size. | ||
| /// | ||
| /// # Example: | ||
| /// ``` | ||
|
|
||
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.
The allocated size was different than what was obtained by
push_accountedprior to this change