Allow larger preallocated capacity for smaller elements

This commit is contained in:
David Tolnay
2023-07-08 13:34:23 -07:00
parent 3686277e14
commit 399ef081ec
3 changed files with 31 additions and 15 deletions
+10 -9
View File
@@ -681,8 +681,8 @@ impl<'de> Visitor<'de> for CStringVisitor {
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
let len = size_hint::cautious(seq.size_hint()); let capacity = size_hint::cautious::<u8>(seq.size_hint());
let mut values = Vec::with_capacity(len); let mut values = Vec::<u8>::with_capacity(capacity);
while let Some(value) = try!(seq.next_element()) { while let Some(value) = try!(seq.next_element()) {
values.push(value); values.push(value);
@@ -936,7 +936,7 @@ macro_rules! seq_impl {
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
$clear(&mut self.0); $clear(&mut self.0);
$reserve(&mut self.0, size_hint::cautious($access.size_hint())); $reserve(&mut self.0, size_hint::cautious::<T>($access.size_hint()));
// FIXME: try to overwrite old values here? (Vec, VecDeque, LinkedList) // FIXME: try to overwrite old values here? (Vec, VecDeque, LinkedList)
while let Some(value) = try!($access.next_element()) { while let Some(value) = try!($access.next_element()) {
@@ -962,7 +962,7 @@ seq_impl!(
BinaryHeap<T: Ord>, BinaryHeap<T: Ord>,
seq, seq,
BinaryHeap::clear, BinaryHeap::clear,
BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())), BinaryHeap::with_capacity(size_hint::cautious::<T>(seq.size_hint())),
BinaryHeap::reserve, BinaryHeap::reserve,
BinaryHeap::push BinaryHeap::push
); );
@@ -992,7 +992,7 @@ seq_impl!(
HashSet<T: Eq + Hash, S: BuildHasher + Default>, HashSet<T: Eq + Hash, S: BuildHasher + Default>,
seq, seq,
HashSet::clear, HashSet::clear,
HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()), HashSet::with_capacity_and_hasher(size_hint::cautious::<T>(seq.size_hint()), S::default()),
HashSet::reserve, HashSet::reserve,
HashSet::insert HashSet::insert
); );
@@ -1002,7 +1002,7 @@ seq_impl!(
VecDeque<T>, VecDeque<T>,
seq, seq,
VecDeque::clear, VecDeque::clear,
VecDeque::with_capacity(size_hint::cautious(seq.size_hint())), VecDeque::with_capacity(size_hint::cautious::<T>(seq.size_hint())),
VecDeque::reserve, VecDeque::reserve,
VecDeque::push_back VecDeque::push_back
); );
@@ -1036,7 +1036,8 @@ where
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
let mut values = Vec::with_capacity(size_hint::cautious(seq.size_hint())); let capacity = size_hint::cautious::<T>(seq.size_hint());
let mut values = Vec::<T>::with_capacity(capacity);
while let Some(value) = try!(seq.next_element()) { while let Some(value) = try!(seq.next_element()) {
values.push(value); values.push(value);
@@ -1072,7 +1073,7 @@ where
where where
A: SeqAccess<'de>, A: SeqAccess<'de>,
{ {
let hint = size_hint::cautious(seq.size_hint()); let hint = size_hint::cautious::<T>(seq.size_hint());
if let Some(additional) = hint.checked_sub(self.0.len()) { if let Some(additional) = hint.checked_sub(self.0.len()) {
self.0.reserve(additional); self.0.reserve(additional);
} }
@@ -1416,7 +1417,7 @@ map_impl!(BTreeMap<K: Ord, V>, map, BTreeMap::new());
map_impl!( map_impl!(
HashMap<K: Eq + Hash, V, S: BuildHasher + Default>, HashMap<K: Eq + Hash, V, S: BuildHasher + Default>,
map, map,
HashMap::with_capacity_and_hasher(size_hint::cautious(map.size_hint()), S::default()) HashMap::with_capacity_and_hasher(size_hint::cautious::<(K, V)>(map.size_hint()), S::default())
); );
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
+10 -3
View File
@@ -474,7 +474,8 @@ mod content {
where where
V: SeqAccess<'de>, V: SeqAccess<'de>,
{ {
let mut vec = Vec::with_capacity(size_hint::cautious(visitor.size_hint())); let mut vec =
Vec::<Content>::with_capacity(size_hint::cautious::<Content>(visitor.size_hint()));
while let Some(e) = try!(visitor.next_element()) { while let Some(e) = try!(visitor.next_element()) {
vec.push(e); vec.push(e);
} }
@@ -485,7 +486,10 @@ mod content {
where where
V: MapAccess<'de>, V: MapAccess<'de>,
{ {
let mut vec = Vec::with_capacity(size_hint::cautious(visitor.size_hint())); let mut vec =
Vec::<(Content, Content)>::with_capacity(
size_hint::cautious::<(Content, Content)>(visitor.size_hint()),
);
while let Some(kv) = try!(visitor.next_entry()) { while let Some(kv) = try!(visitor.next_entry()) {
vec.push(kv); vec.push(kv);
} }
@@ -844,7 +848,10 @@ mod content {
M: MapAccess<'de>, M: MapAccess<'de>,
{ {
let mut tag = None; let mut tag = None;
let mut vec = Vec::with_capacity(size_hint::cautious(map.size_hint())); let mut vec = Vec::<(Content, Content)>::with_capacity(size_hint::cautious::<(
Content,
Content,
)>(map.size_hint()));
while let Some(k) = try!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) { while let Some(k) = try!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) {
match k { match k {
TagOrContent::Tag => { TagOrContent::Tag => {
+11 -3
View File
@@ -8,9 +8,17 @@ where
} }
#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
#[inline] pub fn cautious<Element>(hint: Option<usize>) -> usize {
pub fn cautious(hint: Option<usize>) -> usize { const MAX_PREALLOC_BYTES: usize = 1024 * 1024;
cmp::min(hint.unwrap_or(0), 4096)
if mem::size_of::<Element>() == 0 {
0
} else {
cmp::min(
hint.unwrap_or(0),
MAX_PREALLOC_BYTES / mem::size_of::<Element>(),
)
}
} }
fn helper(bounds: (usize, Option<usize>)) -> Option<usize> { fn helper(bounds: (usize, Option<usize>)) -> Option<usize> {