Skip to content

Commit a622b8a

Browse files
authored
Merge pull request #2495 from dtolnay/cautious
Allow larger preallocated capacity for smaller elements
2 parents 3686277 + 399ef08 commit a622b8a

File tree

3 files changed

+31
-15
lines changed

3 files changed

+31
-15
lines changed

serde/src/de/impls.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -681,8 +681,8 @@ impl<'de> Visitor<'de> for CStringVisitor {
681681
where
682682
A: SeqAccess<'de>,
683683
{
684-
let len = size_hint::cautious(seq.size_hint());
685-
let mut values = Vec::with_capacity(len);
684+
let capacity = size_hint::cautious::<u8>(seq.size_hint());
685+
let mut values = Vec::<u8>::with_capacity(capacity);
686686

687687
while let Some(value) = try!(seq.next_element()) {
688688
values.push(value);
@@ -936,7 +936,7 @@ macro_rules! seq_impl {
936936
A: SeqAccess<'de>,
937937
{
938938
$clear(&mut self.0);
939-
$reserve(&mut self.0, size_hint::cautious($access.size_hint()));
939+
$reserve(&mut self.0, size_hint::cautious::<T>($access.size_hint()));
940940

941941
// FIXME: try to overwrite old values here? (Vec, VecDeque, LinkedList)
942942
while let Some(value) = try!($access.next_element()) {
@@ -962,7 +962,7 @@ seq_impl!(
962962
BinaryHeap<T: Ord>,
963963
seq,
964964
BinaryHeap::clear,
965-
BinaryHeap::with_capacity(size_hint::cautious(seq.size_hint())),
965+
BinaryHeap::with_capacity(size_hint::cautious::<T>(seq.size_hint())),
966966
BinaryHeap::reserve,
967967
BinaryHeap::push
968968
);
@@ -992,7 +992,7 @@ seq_impl!(
992992
HashSet<T: Eq + Hash, S: BuildHasher + Default>,
993993
seq,
994994
HashSet::clear,
995-
HashSet::with_capacity_and_hasher(size_hint::cautious(seq.size_hint()), S::default()),
995+
HashSet::with_capacity_and_hasher(size_hint::cautious::<T>(seq.size_hint()), S::default()),
996996
HashSet::reserve,
997997
HashSet::insert
998998
);
@@ -1002,7 +1002,7 @@ seq_impl!(
10021002
VecDeque<T>,
10031003
seq,
10041004
VecDeque::clear,
1005-
VecDeque::with_capacity(size_hint::cautious(seq.size_hint())),
1005+
VecDeque::with_capacity(size_hint::cautious::<T>(seq.size_hint())),
10061006
VecDeque::reserve,
10071007
VecDeque::push_back
10081008
);
@@ -1036,7 +1036,8 @@ where
10361036
where
10371037
A: SeqAccess<'de>,
10381038
{
1039-
let mut values = Vec::with_capacity(size_hint::cautious(seq.size_hint()));
1039+
let capacity = size_hint::cautious::<T>(seq.size_hint());
1040+
let mut values = Vec::<T>::with_capacity(capacity);
10401041

10411042
while let Some(value) = try!(seq.next_element()) {
10421043
values.push(value);
@@ -1072,7 +1073,7 @@ where
10721073
where
10731074
A: SeqAccess<'de>,
10741075
{
1075-
let hint = size_hint::cautious(seq.size_hint());
1076+
let hint = size_hint::cautious::<T>(seq.size_hint());
10761077
if let Some(additional) = hint.checked_sub(self.0.len()) {
10771078
self.0.reserve(additional);
10781079
}
@@ -1416,7 +1417,7 @@ map_impl!(BTreeMap<K: Ord, V>, map, BTreeMap::new());
14161417
map_impl!(
14171418
HashMap<K: Eq + Hash, V, S: BuildHasher + Default>,
14181419
map,
1419-
HashMap::with_capacity_and_hasher(size_hint::cautious(map.size_hint()), S::default())
1420+
HashMap::with_capacity_and_hasher(size_hint::cautious::<(K, V)>(map.size_hint()), S::default())
14201421
);
14211422

14221423
////////////////////////////////////////////////////////////////////////////////

serde/src/private/de.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,8 @@ mod content {
474474
where
475475
V: SeqAccess<'de>,
476476
{
477-
let mut vec = Vec::with_capacity(size_hint::cautious(visitor.size_hint()));
477+
let mut vec =
478+
Vec::<Content>::with_capacity(size_hint::cautious::<Content>(visitor.size_hint()));
478479
while let Some(e) = try!(visitor.next_element()) {
479480
vec.push(e);
480481
}
@@ -485,7 +486,10 @@ mod content {
485486
where
486487
V: MapAccess<'de>,
487488
{
488-
let mut vec = Vec::with_capacity(size_hint::cautious(visitor.size_hint()));
489+
let mut vec =
490+
Vec::<(Content, Content)>::with_capacity(
491+
size_hint::cautious::<(Content, Content)>(visitor.size_hint()),
492+
);
489493
while let Some(kv) = try!(visitor.next_entry()) {
490494
vec.push(kv);
491495
}
@@ -844,7 +848,10 @@ mod content {
844848
M: MapAccess<'de>,
845849
{
846850
let mut tag = None;
847-
let mut vec = Vec::with_capacity(size_hint::cautious(map.size_hint()));
851+
let mut vec = Vec::<(Content, Content)>::with_capacity(size_hint::cautious::<(
852+
Content,
853+
Content,
854+
)>(map.size_hint()));
848855
while let Some(k) = try!(map.next_key_seed(TagOrContentVisitor::new(self.tag_name))) {
849856
match k {
850857
TagOrContent::Tag => {

serde/src/private/size_hint.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,17 @@ where
88
}
99

1010
#[cfg(any(feature = "std", feature = "alloc"))]
11-
#[inline]
12-
pub fn cautious(hint: Option<usize>) -> usize {
13-
cmp::min(hint.unwrap_or(0), 4096)
11+
pub fn cautious<Element>(hint: Option<usize>) -> usize {
12+
const MAX_PREALLOC_BYTES: usize = 1024 * 1024;
13+
14+
if mem::size_of::<Element>() == 0 {
15+
0
16+
} else {
17+
cmp::min(
18+
hint.unwrap_or(0),
19+
MAX_PREALLOC_BYTES / mem::size_of::<Element>(),
20+
)
21+
}
1422
}
1523

1624
fn helper(bounds: (usize, Option<usize>)) -> Option<usize> {

0 commit comments

Comments
 (0)