mirror of
https://github.com/tokio-rs/bytes.git
synced 2026-08-29 00:00:15 +02:00
Fix reserve over allocating underlying buffer (#560)
Fixes calls to `reserve` when the underlying shared buffer was already big enough to fit the requested capacity. Previously a new even larger buffer was created anyways. This could eventually lead to an OOM condition.
This commit is contained in:
+4
-1
@@ -670,7 +670,10 @@ impl BytesMut {
|
|||||||
|
|
||||||
// Compare the condition in the `kind == KIND_VEC` case above
|
// Compare the condition in the `kind == KIND_VEC` case above
|
||||||
// for more details.
|
// for more details.
|
||||||
if v_capacity >= new_cap && offset >= len {
|
if v_capacity >= new_cap + offset {
|
||||||
|
self.cap = new_cap;
|
||||||
|
// no copy is necessary
|
||||||
|
} else if v_capacity >= new_cap && offset >= len {
|
||||||
// The capacity is sufficient, and copying is not too much
|
// The capacity is sufficient, and copying is not too much
|
||||||
// overhead: reclaim the buffer!
|
// overhead: reclaim the buffer!
|
||||||
|
|
||||||
|
|||||||
@@ -515,6 +515,34 @@ fn reserve_in_arc_unique_doubles() {
|
|||||||
assert_eq!(2000, bytes.capacity());
|
assert_eq!(2000, bytes.capacity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reserve_in_arc_unique_does_not_overallocate_after_split() {
|
||||||
|
let mut bytes = BytesMut::from(LONG);
|
||||||
|
let orig_capacity = bytes.capacity();
|
||||||
|
drop(bytes.split_off(LONG.len() / 2));
|
||||||
|
|
||||||
|
// now bytes is Arc and refcount == 1
|
||||||
|
|
||||||
|
let new_capacity = bytes.capacity();
|
||||||
|
bytes.reserve(orig_capacity - new_capacity);
|
||||||
|
assert_eq!(bytes.capacity(), orig_capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reserve_in_arc_unique_does_not_overallocate_after_multiple_splits() {
|
||||||
|
let mut bytes = BytesMut::from(LONG);
|
||||||
|
let orig_capacity = bytes.capacity();
|
||||||
|
for _ in 0..10 {
|
||||||
|
drop(bytes.split_off(LONG.len() / 2));
|
||||||
|
|
||||||
|
// now bytes is Arc and refcount == 1
|
||||||
|
|
||||||
|
let new_capacity = bytes.capacity();
|
||||||
|
bytes.reserve(orig_capacity - new_capacity);
|
||||||
|
}
|
||||||
|
assert_eq!(bytes.capacity(), orig_capacity);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn reserve_in_arc_nonunique_does_not_overallocate() {
|
fn reserve_in_arc_nonunique_does_not_overallocate() {
|
||||||
let mut bytes = BytesMut::with_capacity(1000);
|
let mut bytes = BytesMut::with_capacity(1000);
|
||||||
|
|||||||
Reference in New Issue
Block a user