Skip to content

Commit

Permalink
Optimize BytesMut::reserve: Reuse vec if possible (#529)
Browse files Browse the repository at this point in the history
* Optimize `BytesMut::reserve`: Reuse vec if possible

If the `BytesMut` holds a unqiue reference to `KIND_ARC` while the
capacity of the `Vec` is not big enough , reuse the existing `Vec`
instead of allocating a new one.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
  • Loading branch information
NobodyXu authored Mar 16, 2022
1 parent 88f5e12 commit d4f5023
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 13 deletions.
40 changes: 28 additions & 12 deletions src/bytes_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -644,21 +644,37 @@ impl BytesMut {

self.ptr = vptr(ptr);
self.cap = v.capacity();
} else {
// calculate offset
let off = v.capacity() - self.cap;

// new_cap is calculated in terms of `BytesMut`, not the underlying
// `Vec`, so it does not take the offset into account.
//
// Thus we have to manually add it here.
new_cap = new_cap.checked_add(off).expect("overflow");

// The vector capacity is not sufficient. The reserve request is
// asking for more than the initial buffer capacity. Allocate more
// than requested if `new_cap` is not much bigger than the current
// capacity.
//
// There are some situations, using `reserve_exact` that the
// buffer capacity could be below `original_capacity`, so do a
// check.
let double = v.capacity().checked_shl(1).unwrap_or(new_cap);

new_cap = cmp::max(double, new_cap);

return;
// No space - allocate more
v.reserve(new_cap - v.len());

// Update the info
self.ptr = vptr(v.as_mut_ptr().add(off));
self.cap = v.capacity() - off;
}

// The vector capacity is not sufficient. The reserve request is
// asking for more than the initial buffer capacity. Allocate more
// than requested if `new_cap` is not much bigger than the current
// capacity.
//
// There are some situations, using `reserve_exact` that the
// buffer capacity could be below `original_capacity`, so do a
// check.
let double = v.capacity().checked_shl(1).unwrap_or(new_cap);

new_cap = cmp::max(cmp::max(double, new_cap), original_capacity);
return;
} else {
new_cap = cmp::max(new_cap, original_capacity);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/test_bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ fn reserve_growth() {
let _ = bytes.split();

bytes.reserve(65);
assert_eq!(bytes.capacity(), 128);
assert_eq!(bytes.capacity(), 117);
}

#[test]
Expand Down

0 comments on commit d4f5023

Please sign in to comment.