mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-26 16:28:15 +00:00
perf(hotpath): add fine-grained PUT-path stage guards (HP-14) (#4541)
Close the ~10ms instrumentation residual on the PUT success path that the existing coarse writer_setup/encode/rename stage metrics do not attribute. Adds `hp_guard!` measurement scopes to the previously uninstrumented sub-stages called out in backlog#935 item 2: - SetDisks::acquire_read_lock / acquire_write_lock (namespace lock acquire) - S3::put_object_prelookup (pre-write get_object_info lookup) - MultiWriter::shutdown (bitrot writer flush/close) - SetDisks::commit_rename_data_dir (old data-dir reclaim) - S3Access::put_object (S3 authorization segment) Instrumentation only: `hp_guard!` expands to nothing without the `hotpath` feature, so this is a pure-observation change with zero behavior impact and zero cost in default builds. The pre-lookup site wraps only the lookup call in a scoped block so the guard measures that slice exactly while preserving the existing match and control flow. Verified: cargo check -p rustfs-ecstore (default and --features hotpath) and cargo check -p rustfs (default and --features hotpath) all pass. Co-authored-by: heihutu <heihutu@gmail.com>
This commit is contained in:
@@ -279,6 +279,7 @@ impl<'a> MultiWriter<'a> {
|
||||
}
|
||||
|
||||
pub async fn shutdown(&mut self) -> std::io::Result<()> {
|
||||
crate::hp_guard!("MultiWriter::shutdown");
|
||||
{
|
||||
let mut futures = FuturesUnordered::new();
|
||||
for (writer_opt, err) in self.writers.iter_mut().zip(self.errs.iter_mut()) {
|
||||
|
||||
@@ -2744,6 +2744,7 @@ impl SetDisks {
|
||||
committed_data_dir: &str,
|
||||
write_quorum: usize,
|
||||
) -> OldDataDirCleanup {
|
||||
crate::hp_guard!("SetDisks::commit_rename_data_dir");
|
||||
// Anti-misdelete guard (parity retained): MinIO sets `res.OldDataDir=""`
|
||||
// when old == new (`xl-storage.go:2796`) and `commitRenameDataDir` skips
|
||||
// the empty value (`:1837`). Rather miss a reclaim than delete the data
|
||||
|
||||
@@ -1648,6 +1648,7 @@ impl SetDisks {
|
||||
}
|
||||
|
||||
async fn acquire_read_lock_diag(&self, op: &'static str, bucket: &str, object: &str) -> Result<ObjectLockDiagGuard> {
|
||||
crate::hp_guard!("SetDisks::acquire_read_lock");
|
||||
let diag_enabled = is_object_lock_diag_enabled();
|
||||
let ns_lock = self.new_ns_lock(bucket, object).await?;
|
||||
let acquire_start = Instant::now();
|
||||
@@ -1669,6 +1670,7 @@ impl SetDisks {
|
||||
}
|
||||
|
||||
async fn acquire_write_lock_diag(&self, op: &'static str, bucket: &str, object: &str) -> Result<ObjectLockDiagGuard> {
|
||||
crate::hp_guard!("SetDisks::acquire_write_lock");
|
||||
let diag_enabled = is_object_lock_diag_enabled();
|
||||
let ns_lock = self.new_ns_lock(bucket, object).await?;
|
||||
let acquire_start = Instant::now();
|
||||
|
||||
@@ -3515,7 +3515,11 @@ impl DefaultObjectUsecase {
|
||||
.await
|
||||
.map_err(ApiError::from)?,
|
||||
);
|
||||
let previous_current_size = match store.get_object_info(&bucket, &key, ¤t_opts).await {
|
||||
let previous_current_info = {
|
||||
crate::hp_guard!("S3::put_object_prelookup");
|
||||
store.get_object_info(&bucket, &key, ¤t_opts).await
|
||||
};
|
||||
let previous_current_size = match previous_current_info {
|
||||
Ok(existing_obj_info) => {
|
||||
validate_existing_object_lock_for_write(&existing_obj_info, &opts)?;
|
||||
Some(existing_obj_info.size.max(0) as u64)
|
||||
|
||||
@@ -1869,6 +1869,7 @@ impl S3Access for FS {
|
||||
///
|
||||
/// This method returns `Ok(())` by default.
|
||||
async fn put_object(&self, req: &mut S3Request<PutObjectInput>) -> S3Result<()> {
|
||||
crate::hp_guard!("S3Access::put_object");
|
||||
let req_info = ext_req_info_mut(&mut req.extensions)?;
|
||||
req_info.bucket = Some(req.input.bucket.clone());
|
||||
req_info.object = Some(req.input.key.clone());
|
||||
|
||||
Reference in New Issue
Block a user