mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-29 08:27:06 +00:00
feat(ecstore): add deeper zero-copy ingest experiment (#3847)
* feat(storage): add multipart put stage metrics * feat(scripts): add multipart put focus runner * docs(operations): add multipart put server-path guides * chore(scripts): add local rustfs restart helper * docs(observability): add local metrics backend guide * docs(observability): add localized multipart guides * fix(ecstore): validate multipart batching path * feat(obs): add erasure encode overlap metrics * docs(ops): update overlap retest summary * docs(ops): add batchblocks retest matrix * docs(ops): extend overlap candidate summary * docs(ops): capture 8-run overlap summary * feat(storage): switch rename_data to msgpack map * test(storage): add rename_data payload checks * feat(object): add zero_copy_eager put path * docs(ops): add zero_copy_eager put guide * docs(ops): add deeper zero-copy next steps * feat(ecstore): add bytesmut erasure ingest gate * docs(ops): add bytesmut ingest summary * docs(ops): extend bytesmut ingest matrix summary * docs(ops): extend bytesmut larger-object summary * docs(ops): capture bytesmut variability summary * chore(scripts): add deeper zero-copy capture flow * chore(scripts): add deeper zero-copy capture support * docs(ops): add capture-backed bytesmut retest * docs(ops): update deeper zero-copy retests * chore(docs): keep issue-712 notes local only Co-Authored-By: heihutu <heihutu@gmail.com>
This commit is contained in:
@@ -565,6 +565,53 @@ impl Erasure {
|
||||
Ok(shards)
|
||||
}
|
||||
|
||||
/// Encode data from an owned `BytesMut` buffer, avoiding the initial copy
|
||||
/// from a borrowed slice into a fresh `BytesMut`.
|
||||
pub fn encode_data_bytes_mut(&self, mut data_buffer: BytesMut, data_len: usize) -> io::Result<Vec<Bytes>> {
|
||||
let shard_size_fn = if self.uses_legacy {
|
||||
calc_shard_size_legacy
|
||||
} else {
|
||||
calc_shard_size
|
||||
};
|
||||
let per_shard_size = shard_size_fn(data_len, self.data_shards);
|
||||
if per_shard_size == 0 {
|
||||
return Ok(vec![Bytes::new(); self.total_shard_count()]);
|
||||
}
|
||||
let need_total_size = per_shard_size * self.total_shard_count();
|
||||
|
||||
if data_buffer.len() > data_len {
|
||||
data_buffer.truncate(data_len);
|
||||
}
|
||||
data_buffer.resize(need_total_size, 0u8);
|
||||
|
||||
{
|
||||
let data_slices: SmallVec<[&mut [u8]; 16]> = data_buffer.chunks_exact_mut(per_shard_size).collect();
|
||||
|
||||
if self.parity_shards > 0 {
|
||||
if self.uses_legacy {
|
||||
if let Some(encoder) = self.legacy_encoder.as_ref() {
|
||||
encoder.encode(data_slices)?;
|
||||
} else {
|
||||
warn!("parity_shards > 0, uses_legacy but legacy_encoder is None");
|
||||
}
|
||||
} else if let Some(encoder) = self.encoder.as_ref() {
|
||||
encoder.encode(data_slices)?;
|
||||
} else {
|
||||
warn!("parity_shards > 0, but encoder is None");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut data_buffer = data_buffer.freeze();
|
||||
let mut shards = Vec::with_capacity(self.total_shard_count());
|
||||
for _ in 0..self.total_shard_count() {
|
||||
let shard = data_buffer.split_to(per_shard_size);
|
||||
shards.push(shard);
|
||||
}
|
||||
|
||||
Ok(shards)
|
||||
}
|
||||
|
||||
/// Decode and reconstruct missing data shards in-place.
|
||||
///
|
||||
/// # Arguments
|
||||
@@ -799,6 +846,21 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_data_bytes_mut_matches_borrowed_path() {
|
||||
for uses_legacy in [false, true] {
|
||||
let erasure = Erasure::new_with_options(4, 2, 64, uses_legacy);
|
||||
for data in [Vec::new(), b"small payload".to_vec(), (0_u8..37).collect::<Vec<_>>()] {
|
||||
let borrowed = erasure.encode_data(&data).expect("borrowed encode should succeed");
|
||||
let bytes_mut = BytesMut::from(&data[..]);
|
||||
let owned = erasure
|
||||
.encode_data_bytes_mut(bytes_mut, data.len())
|
||||
.expect("bytesmut encode should succeed");
|
||||
assert_eq!(owned, borrowed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decode_data_keeps_missing_parity_shard_unreconstructed() {
|
||||
let erasure = Erasure::new(2, 2, 64);
|
||||
|
||||
Reference in New Issue
Block a user