Skip to content

Commit cb97a7e

Browse files
committed
Removed unnecessary intermediate Vec<Bytes> allocation in HTTP request body preparation
- Removed unnecessary intermediate `Vec<Bytes>` allocation in HTTP request body preparation - Directly consume `SegmentedBytes` iterator into stream using `Arc::unwrap_or_clone()` - Implemented zero-cost `BodyIterator` enum to avoid heap allocation and dynamic dispatch - Reduces memory overhead and eliminates Vec growth reallocations during request preparation
1 parent 1ee21b7 commit cb97a7e

File tree

1 file changed

+20
-7
lines changed

1 file changed

+20
-7
lines changed

src/s3/client.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,22 @@ pub const MAX_PART_SIZE: u64 = 5_368_709_120; // 5 GiB
115115
/// ensuring the object does not exceed 5 TiB.
116116
pub const MAX_OBJECT_SIZE: u64 = 5_497_558_138_880; // 5 TiB
117117

118+
enum BodyIterator {
119+
Segmented(crate::s3::segmented_bytes::SegmentedBytesIntoIterator),
120+
Empty(std::iter::Empty<Bytes>),
121+
}
122+
123+
impl Iterator for BodyIterator {
124+
type Item = Bytes;
125+
126+
fn next(&mut self) -> Option<Self::Item> {
127+
match self {
128+
Self::Segmented(iter) => iter.next(),
129+
Self::Empty(iter) => iter.next(),
130+
}
131+
}
132+
}
133+
118134
/// Maximum number of parts allowed in a multipart upload.
119135
///
120136
/// Multipart uploads are limited to a total of 10,000 parts. If the object
@@ -521,14 +537,11 @@ impl MinioClient {
521537
}
522538

523539
if (*method == Method::PUT) || (*method == Method::POST) {
524-
//TODO: why-oh-why first collect into a vector and then iterate to a stream?
525-
let bytes_vec: Vec<Bytes> = match body {
526-
Some(v) => v.iter().collect(),
527-
None => Vec::new(),
540+
let iter = match body {
541+
Some(v) => BodyIterator::Segmented(Arc::unwrap_or_clone(v).into_iter()),
542+
None => BodyIterator::Empty(std::iter::empty()),
528543
};
529-
let stream = futures_util::stream::iter(
530-
bytes_vec.into_iter().map(|b| -> Result<_, Error> { Ok(b) }),
531-
);
544+
let stream = futures_util::stream::iter(iter.map(|b| -> Result<_, Error> { Ok(b) }));
532545
req = req.body(Body::wrap_stream(stream));
533546
}
534547

0 commit comments

Comments
 (0)