Skip to content

Commit d4f5023

Browse files
authored
Optimize BytesMut::reserve: Reuse vec if possible (#529)
* 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>
1 parent 88f5e12 commit d4f5023

File tree

2 files changed

+29
-13
lines changed

2 files changed

+29
-13
lines changed

src/bytes_mut.rs

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -644,21 +644,37 @@ impl BytesMut {
644644

645645
self.ptr = vptr(ptr);
646646
self.cap = v.capacity();
647+
} else {
648+
// calculate offset
649+
let off = v.capacity() - self.cap;
650+
651+
// new_cap is calculated in terms of `BytesMut`, not the underlying
652+
// `Vec`, so it does not take the offset into account.
653+
//
654+
// Thus we have to manually add it here.
655+
new_cap = new_cap.checked_add(off).expect("overflow");
656+
657+
// The vector capacity is not sufficient. The reserve request is
658+
// asking for more than the initial buffer capacity. Allocate more
659+
// than requested if `new_cap` is not much bigger than the current
660+
// capacity.
661+
//
662+
// There are some situations, using `reserve_exact` that the
663+
// buffer capacity could be below `original_capacity`, so do a
664+
// check.
665+
let double = v.capacity().checked_shl(1).unwrap_or(new_cap);
666+
667+
new_cap = cmp::max(double, new_cap);
647668

648-
return;
669+
// No space - allocate more
670+
v.reserve(new_cap - v.len());
671+
672+
// Update the info
673+
self.ptr = vptr(v.as_mut_ptr().add(off));
674+
self.cap = v.capacity() - off;
649675
}
650676

651-
// The vector capacity is not sufficient. The reserve request is
652-
// asking for more than the initial buffer capacity. Allocate more
653-
// than requested if `new_cap` is not much bigger than the current
654-
// capacity.
655-
//
656-
// There are some situations, using `reserve_exact` that the
657-
// buffer capacity could be below `original_capacity`, so do a
658-
// check.
659-
let double = v.capacity().checked_shl(1).unwrap_or(new_cap);
660-
661-
new_cap = cmp::max(cmp::max(double, new_cap), original_capacity);
677+
return;
662678
} else {
663679
new_cap = cmp::max(new_cap, original_capacity);
664680
}

tests/test_bytes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ fn reserve_growth() {
443443
let _ = bytes.split();
444444

445445
bytes.reserve(65);
446-
assert_eq!(bytes.capacity(), 128);
446+
assert_eq!(bytes.capacity(), 117);
447447
}
448448

449449
#[test]

0 commit comments

Comments
 (0)