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:
houseme
2026-05-19 18:20:24 +08:00
committed by GitHub
parent f695870626
commit 25c6bdf490
16 changed files with 1059 additions and 177 deletions
+32 -8
View File
@@ -54,6 +54,17 @@ pub fn register_profiling_route(r: &mut S3Router<AdminOperation>) -> std::io::Re
pub struct ProfileHandler {}
#[allow(dead_code)]
fn map_cpu_profile_collect_error_message(err: &str) -> (StatusCode, String) {
if err.contains("start running cpu profiler error") {
return (
StatusCode::CONFLICT,
"CPU profiler is already running. Disable RUSTFS_OBS_PROFILING_EXPORT_ENABLED or retry later.".to_string(),
);
}
(StatusCode::INTERNAL_SERVER_ERROR, format!("Failed to collect CPU profile: {err}"))
}
#[async_trait::async_trait]
impl Operation for ProfileHandler {
async fn call(&self, req: S3Request<Body>, _params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
@@ -95,15 +106,19 @@ impl Operation for ProfileHandler {
headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/octet-stream"));
Ok(S3Response::with_headers((StatusCode::OK, Body::from(bytes)), headers))
}
Err(e) => Ok(S3Response::new((
StatusCode::INTERNAL_SERVER_ERROR,
Body::from(format!("Failed to read profile file: {e}")),
))),
Err(e) => {
error!("Failed to read profile file {}: {}", path.display(), e);
Ok(S3Response::new((
StatusCode::INTERNAL_SERVER_ERROR,
Body::from(format!("Failed to read profile file: {e}")),
)))
}
},
Err(e) => Ok(S3Response::new((
StatusCode::INTERNAL_SERVER_ERROR,
Body::from(format!("Failed to collect CPU profile: {e}")),
))),
Err(e) => {
let (status, message) = map_cpu_profile_collect_error_message(&e);
error!("CPU protobuf profile collection failed: {}", e);
Ok(S3Response::new((status, Body::from(message))))
}
},
"flamegraph" | "svg" => {
let freq = get_env_usize(ENV_CPU_FREQ, DEFAULT_CPU_FREQ) as i32;
@@ -213,6 +228,7 @@ mod tests {
use crate::admin::router::Operation;
use http::{Extensions, HeaderMap, Uri};
use hyper::Method;
use hyper::StatusCode;
use matchit::Params;
use s3s::{Body, S3ErrorCode, S3Request};
@@ -268,4 +284,12 @@ mod tests {
assert_eq!(err.code(), &S3ErrorCode::AccessDenied);
assert_eq!(err.message(), Some("Signature is required"));
}
#[test]
fn cpu_profile_collect_error_maps_profiler_conflict_to_409() {
let (status, message) =
super::map_cpu_profile_collect_error_message("create profiler failed: start running cpu profiler error");
assert_eq!(status, StatusCode::CONFLICT);
assert!(message.contains("CPU profiler is already running"));
}
}
+4 -1
View File
@@ -196,7 +196,10 @@ pub struct ServerOpts {
)]
pub console_address: String,
/// Observability endpoint for trace, metrics and logs,only support grpc mode.
/// Root OTLP endpoint for traces, metrics, and logs.
/// For the current observability pipeline this should be an OTLP/HTTP base
/// URL such as `http://otel-collector:4318` or
/// `http://host.docker.internal:4318`.
#[arg(
long,
default_value_t = rustfs_config::DEFAULT_OBS_ENDPOINT.to_string(),