mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-22 12:26:37 +00:00
perf(filemeta): phase-1~3 rename_data metadata optimization (#3011)
* chore(perf): harden amd64 profiling benchmark flow * fix(profiling): isolate bench buckets and map protobuf conflict * perf: avoid blocking owned local writes * style: format profile admin handler * docs: clarify observability trace validation * perf: reduce mkdir overhead on local writes * perf: add rename_data meta microbenchmark * perf(filemeta): fast-path data_dir decode in version meta * perf(filemeta): collapse data-dir lookup into one scan * perf(filemeta): reduce scan allocs and refresh meta bench * perf(ecstore): skip mkdir path on read-only open * perf(filemeta): single-pass unshared data-dir scan * perf(filemeta): add two-key inline remove fast path * perf(filemeta): compare remove-two keys by bytes first * bench(ecstore): add remove_two-only micro benchmark * bench(ecstore): stabilize rename_data meta benchmark timing * bench(ecstore): align rename_data path with remove_two * perf(filemeta): avoid uuid string alloc in remove_two * perf(filemeta): add fast-path for empty inline data * perf(filemeta): streamline add_version match branch * perf(filemeta): fast-return remove_key on miss * perf(filemeta): speed up add_version insertion lookup * style(ecstore): normalize formatting in perf-tuning files * refactor(filemeta): unify inline data removal paths
This commit is contained in:
@@ -1194,7 +1194,9 @@ impl LocalDisk {
|
||||
skip_parent = self.root.as_path();
|
||||
}
|
||||
|
||||
if let Some(parent) = path.as_ref().parent() {
|
||||
if let Some(parent) = path.as_ref().parent()
|
||||
&& parent != skip_parent
|
||||
{
|
||||
os::make_dir_all(parent, skip_parent).await?;
|
||||
}
|
||||
|
||||
@@ -1203,6 +1205,11 @@ impl LocalDisk {
|
||||
Ok(f)
|
||||
}
|
||||
|
||||
async fn open_file_read_only(&self, path: impl AsRef<Path>) -> Result<File> {
|
||||
let f = super::fs::open_file(path.as_ref(), O_RDONLY).await.map_err(to_file_error)?;
|
||||
Ok(f)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn get_metrics(&self) -> DiskMetrics {
|
||||
DiskMetrics::default()
|
||||
@@ -2137,7 +2144,7 @@ impl DiskAPI for LocalDisk {
|
||||
let file_path = self.get_object_path(volume, path)?;
|
||||
check_path_length(file_path.to_string_lossy().as_ref())?;
|
||||
|
||||
let f = self.open_file(file_path, O_RDONLY, volume_dir).await?;
|
||||
let f = self.open_file_read_only(file_path).await?;
|
||||
|
||||
Ok(Box::new(f))
|
||||
}
|
||||
@@ -2154,7 +2161,7 @@ impl DiskAPI for LocalDisk {
|
||||
let file_path = self.get_object_path(volume, path)?;
|
||||
check_path_length(file_path.to_string_lossy().as_ref())?;
|
||||
|
||||
let mut f = self.open_file(file_path, O_RDONLY, volume_dir).await?;
|
||||
let mut f = self.open_file_read_only(file_path).await?;
|
||||
|
||||
let meta = f.metadata().await?;
|
||||
let end_offset = offset.checked_add(length).ok_or(DiskError::FileCorrupt)?;
|
||||
@@ -2513,32 +2520,41 @@ impl DiskAPI for LocalDisk {
|
||||
|
||||
// TODO: Healing
|
||||
|
||||
let search_version_id = fi.version_id.or(Some(Uuid::nil()));
|
||||
let version_id = fi.version_id.unwrap_or_default();
|
||||
let search_version_id = Some(version_id);
|
||||
let no_inline = fi.data.is_none() && fi.size > 0;
|
||||
|
||||
// Check if there's an existing version with the same version_id that has a data_dir to clean up
|
||||
let has_old_data_dir = {
|
||||
xlmeta.find_version(search_version_id).ok().and_then(|(_, ver)| {
|
||||
// shard_count == 0 means no other version shares this data_dir
|
||||
ver.get_data_dir()
|
||||
.filter(|&data_dir| xlmeta.shard_data_dir_count(&search_version_id, &Some(data_dir)) == 0)
|
||||
})
|
||||
};
|
||||
// Reuse one metadata scan to find the version data_dir and determine whether it is shared.
|
||||
let has_old_data_dir = xlmeta.find_unshared_data_dir_for_version(search_version_id);
|
||||
if let Some(old_data_dir) = has_old_data_dir.as_ref() {
|
||||
let _ = xlmeta.data.remove(vec![search_version_id.unwrap_or_default(), *old_data_dir]);
|
||||
let _ = xlmeta.data.remove_two(version_id, *old_data_dir);
|
||||
}
|
||||
|
||||
xlmeta.add_version(fi.clone())?;
|
||||
xlmeta.add_version(fi)?;
|
||||
|
||||
if xlmeta.versions.len() <= 10 {
|
||||
// TODO: Sign
|
||||
}
|
||||
|
||||
let new_dst_buf = xlmeta.marshal_msg()?;
|
||||
|
||||
self.write_all(src_volume, format!("{}/{}", &src_path, STORAGE_FORMAT_FILE).as_str(), new_dst_buf.into())
|
||||
.await?;
|
||||
if let Some((src_data_path, dst_data_path)) = has_data_dir_path.as_ref() {
|
||||
let no_inline = fi.data.is_none() && fi.size > 0;
|
||||
let src_file_parent = src_file_path.parent().unwrap_or(src_volume_dir.as_path());
|
||||
let meta_skip_parent = if no_inline {
|
||||
src_file_parent
|
||||
} else {
|
||||
src_volume_dir.as_path()
|
||||
};
|
||||
let new_dst_buf = xlmeta.marshal_msg()?;
|
||||
|
||||
self.write_all_private(
|
||||
src_volume,
|
||||
format!("{}/{}", &src_path, STORAGE_FORMAT_FILE).as_str(),
|
||||
new_dst_buf.into(),
|
||||
true,
|
||||
meta_skip_parent,
|
||||
)
|
||||
.await?;
|
||||
|
||||
if no_inline && let Err(err) = rename_all(&src_data_path, &dst_data_path, &skip_parent).await {
|
||||
let _ = self.delete_file(&dst_volume_dir, dst_data_path, false, false).await;
|
||||
info!(
|
||||
@@ -2547,6 +2563,10 @@ impl DiskAPI for LocalDisk {
|
||||
);
|
||||
return Err(err);
|
||||
}
|
||||
} else {
|
||||
let new_dst_buf = xlmeta.marshal_msg()?;
|
||||
self.write_all(src_volume, format!("{}/{}", &src_path, STORAGE_FORMAT_FILE).as_str(), new_dst_buf.into())
|
||||
.await?;
|
||||
}
|
||||
|
||||
if let Some(old_data_dir) = has_old_data_dir {
|
||||
|
||||
@@ -215,24 +215,29 @@ pub async fn os_mkdir_all(dir_path: impl AsRef<Path>, base_dir: impl AsRef<Path>
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Some(parent) = dir_path.as_ref().parent() {
|
||||
// Without recursion support, fall back to create_dir_all
|
||||
if let Err(e) = super::fs::make_dir_all(&parent).await {
|
||||
if e.kind() == io::ErrorKind::AlreadyExists {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
return Err(e);
|
||||
}
|
||||
// Box::pin(os_mkdir_all(&parent, &base_dir)).await?;
|
||||
}
|
||||
|
||||
if let Err(e) = super::fs::mkdir(dir_path.as_ref()).await {
|
||||
if e.kind() == io::ErrorKind::AlreadyExists {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
return Err(e);
|
||||
if e.kind() != io::ErrorKind::NotFound {
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
if let Some(parent) = dir_path.as_ref().parent() {
|
||||
// Fall back to creating the missing parent chain only when the direct mkdir proves it is required.
|
||||
if let Err(parent_err) = super::fs::make_dir_all(parent).await
|
||||
&& parent_err.kind() != io::ErrorKind::AlreadyExists
|
||||
{
|
||||
return Err(parent_err);
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(retry_err) = super::fs::mkdir(dir_path.as_ref()).await
|
||||
&& retry_err.kind() != io::ErrorKind::AlreadyExists
|
||||
{
|
||||
return Err(retry_err);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user