mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-28 16:07:05 +00:00
Merge pull request #326 from rustfs/nugine/performance/v4
feat(ecstore/erasure): optimize `encode_data`
This commit is contained in:
Generated
+1
@@ -3090,6 +3090,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"sha2 0.11.0-pre.5",
|
"sha2 0.11.0-pre.5",
|
||||||
"siphasher 1.0.1",
|
"siphasher 1.0.1",
|
||||||
|
"smallvec",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"thiserror 2.0.12",
|
"thiserror 2.0.12",
|
||||||
"time",
|
"time",
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ madmin.workspace = true
|
|||||||
workers.workspace = true
|
workers.workspace = true
|
||||||
reqwest = { workspace = true }
|
reqwest = { workspace = true }
|
||||||
urlencoding = "2.1.3"
|
urlencoding = "2.1.3"
|
||||||
|
smallvec = "1.15.0"
|
||||||
|
|
||||||
[target.'cfg(not(windows))'.dependencies]
|
[target.'cfg(not(windows))'.dependencies]
|
||||||
|
|
||||||
|
|||||||
+23
-19
@@ -1,9 +1,11 @@
|
|||||||
use crate::bitrot::{BitrotReader, BitrotWriter};
|
use crate::bitrot::{BitrotReader, BitrotWriter};
|
||||||
use crate::error::clone_err;
|
use crate::error::clone_err;
|
||||||
use crate::quorum::{object_op_ignored_errs, reduce_write_quorum_errs};
|
use crate::quorum::{object_op_ignored_errs, reduce_write_quorum_errs};
|
||||||
|
use bytes::{Bytes, BytesMut};
|
||||||
use common::error::{Error, Result};
|
use common::error::{Error, Result};
|
||||||
use futures::future::join_all;
|
use futures::future::join_all;
|
||||||
use reed_solomon_erasure::galois_8::ReedSolomon;
|
use reed_solomon_erasure::galois_8::ReedSolomon;
|
||||||
|
use smallvec::SmallVec;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::io::ErrorKind;
|
use std::io::ErrorKind;
|
||||||
use tokio::io::{AsyncRead, AsyncWrite};
|
use tokio::io::{AsyncRead, AsyncWrite};
|
||||||
@@ -66,6 +68,7 @@ impl Erasure {
|
|||||||
// );
|
// );
|
||||||
|
|
||||||
let mut total: usize = 0;
|
let mut total: usize = 0;
|
||||||
|
let mut blocks = <SmallVec<[Bytes; 16]>>::new();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if total_size > 0 {
|
if total_size > 0 {
|
||||||
@@ -97,7 +100,7 @@ impl Erasure {
|
|||||||
total += self.buf.len();
|
total += self.buf.len();
|
||||||
}
|
}
|
||||||
|
|
||||||
let blocks = self.encode_data(&self.buf)?;
|
self.encode_data(&self.buf, &mut blocks)?;
|
||||||
let mut errs = Vec::new();
|
let mut errs = Vec::new();
|
||||||
|
|
||||||
// TODO: 并发写入
|
// TODO: 并发写入
|
||||||
@@ -355,20 +358,20 @@ impl Erasure {
|
|||||||
self.data_shards + self.parity_shards
|
self.data_shards + self.parity_shards
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encode_data(&self, data: &[u8]) -> Result<Vec<Vec<u8>>> {
|
#[tracing::instrument(level = "debug", skip_all, fields(data_len=data.len()))]
|
||||||
|
pub fn encode_data(&self, data: &[u8], shards: &mut SmallVec<[Bytes; 16]>) -> Result<()> {
|
||||||
let (shard_size, total_size) = self.need_size(data.len());
|
let (shard_size, total_size) = self.need_size(data.len());
|
||||||
|
|
||||||
// 生成一个新的 所需的所有分片数据长度
|
// 生成一个新的 所需的所有分片数据长度
|
||||||
let mut data_buffer = vec![0u8; total_size];
|
let mut data_buffer = BytesMut::with_capacity(total_size);
|
||||||
{
|
|
||||||
// 复制源数据
|
// 复制源数据
|
||||||
let (left, _) = data_buffer.split_at_mut(data.len());
|
data_buffer.extend_from_slice(data);
|
||||||
left.copy_from_slice(data);
|
data_buffer.resize(total_size, 0u8);
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
// ec encode, 结果会写进 data_buffer
|
// ec encode, 结果会写进 data_buffer
|
||||||
let data_slices: Vec<&mut [u8]> = data_buffer.chunks_mut(shard_size).collect();
|
let data_slices: SmallVec<[&mut [u8]; 16]> = data_buffer.chunks_exact_mut(shard_size).collect();
|
||||||
|
|
||||||
// partiy 数量大于0 才ec
|
// partiy 数量大于0 才ec
|
||||||
if self.parity_shards > 0 {
|
if self.parity_shards > 0 {
|
||||||
@@ -376,16 +379,16 @@ impl Erasure {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分片
|
// 零拷贝分片,所有 shard 引用 data_buffer
|
||||||
let mut shards = Vec::with_capacity(self.total_shard_count());
|
let mut data_buffer = data_buffer.freeze();
|
||||||
|
shards.clear();
|
||||||
let slices: Vec<&[u8]> = data_buffer.chunks(shard_size).collect();
|
shards.reserve(self.total_shard_count());
|
||||||
|
for _ in 0..self.total_shard_count() {
|
||||||
for &d in slices.iter() {
|
let shard = data_buffer.split_to(shard_size);
|
||||||
shards.push(d.to_vec());
|
shards.push(shard);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(shards)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode_data(&self, shards: &mut [Option<Vec<u8>>]) -> Result<()> {
|
pub fn decode_data(&self, shards: &mut [Option<Vec<u8>>]) -> Result<()> {
|
||||||
@@ -625,12 +628,13 @@ mod test {
|
|||||||
let parity_shards = 2;
|
let parity_shards = 2;
|
||||||
let data: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
|
let data: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
|
||||||
let ec = Erasure::new(data_shards, parity_shards, 1);
|
let ec = Erasure::new(data_shards, parity_shards, 1);
|
||||||
let shards = ec.encode_data(data).unwrap();
|
let mut shards = SmallVec::new();
|
||||||
|
ec.encode_data(data, &mut shards).unwrap();
|
||||||
println!("shards:{:?}", shards);
|
println!("shards:{:?}", shards);
|
||||||
|
|
||||||
let mut s: Vec<_> = shards
|
let mut s: Vec<_> = shards
|
||||||
.iter()
|
.iter()
|
||||||
.map(|d| if d.is_empty() { None } else { Some(d.clone()) })
|
.map(|d| if d.is_empty() { None } else { Some(d.to_vec()) })
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// let mut s = shards_to_option_shards(&shards);
|
// let mut s = shards_to_option_shards(&shards);
|
||||||
|
|||||||
Reference in New Issue
Block a user