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:
houseme
2026-07-09 01:47:14 +08:00
committed by GitHub
parent 0866a8e6a0
commit f262fcfce0
5 changed files with 10 additions and 1 deletions
@@ -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
+2
View File
@@ -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();