]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
cephfs-tool: Add support for dumping performance counters
authorEdwin Rodriguez <edwin.rodriguez1@ibm.com>
Wed, 15 Apr 2026 16:08:43 +0000 (12:08 -0400)
committerEdwin Rodriguez <edwin.rodriguez1@ibm.com>
Wed, 1 Jul 2026 13:11:15 +0000 (09:11 -0400)
Add --perf-dump to write libcephfs client performance counters to a file
at the end of the benchmark. Uses ceph_get_perf_counters() while the
mount is still active so counters reflect the full benchmark run.

Fixes: https://tracker.ceph.com/issues/76183
Signed-off-by: Edwin Rodriguez <edwin.rodriguez1@ibm.com>
src/tools/cephfs/cephfs-tool.cc

index 29b4d9310af68a6173d43c4b61635e3f4c66cced..9762dfc0849cae915faa2dce0c3b7beb7280714d 100644 (file)
@@ -31,6 +31,9 @@
 #include <vector>
 
 #include "common/JSONFormatter.h"
+#include "common/ceph_context.h"
+#include "common/cmdparse.h"
+#include "common/perf_counters_collection.h"
 
 // Standard Public Ceph API
 #include <cephfs/libcephfs.h>
@@ -40,6 +43,8 @@
 // Boost Program Options
 #include <boost/program_options.hpp>
 
+#include "cls/journal/cls_journal_types.h"
+
 using std::cerr;
 using std::cout;
 using std::endl;
@@ -161,6 +166,7 @@ struct BenchConfig {
   int gid;
   string json_path;
   int duration;
+  string perf_dump_path;
 };
 
 struct ThreadStats {
@@ -472,6 +478,35 @@ bench_read_worker(
   }
 }
 
+void
+execute_perf_dump(struct ceph_mount_info* cmount, const string& output_path)
+{
+  if (output_path.empty()) {
+    return;
+  }
+
+  char* perf_dump = nullptr;
+  int rc = ceph_get_perf_counters(cmount, &perf_dump);
+  if (rc < 0) {
+    cerr << "Error: Failed to get performance counters: " << strerror(-rc)
+         << endl;
+    return;
+  }
+
+  if (perf_dump) {
+    std::ofstream ofs(output_path);
+    if (!ofs.is_open()) {
+      cerr << "Error: Could not open " << output_path
+           << " for writing performance counters." << endl;
+      free(perf_dump);
+      return;
+    }
+    ofs << perf_dump;
+    free(perf_dump);
+    cout << "Performance counters dumped to " << output_path << endl;
+  }
+}
+
 // Worker function for Cleanup (Unlink) phase
 void bench_cleanup_worker(int thread_id,
                           int files_to_clean,
@@ -863,9 +898,15 @@ int do_bench(BenchConfig& config) {
     }
   }
 
+  if (!config.perf_dump_path.empty()) {
+    execute_perf_dump(shared_cmount, config.perf_dump_path);
+  }
+
   if (int rc = ceph_unmount(shared_cmount); rc < 0) {
     cerr << "Final unmount failed: " << strerror(-rc) << endl;
   }
+
+
   ceph_shutdown(shared_cmount);
   return 0;
 }
@@ -902,7 +943,8 @@ int main(int argc, char **argv) {
     ("per-thread-mount", po::bool_switch(&config.per_thread_mount), "Use separate mount per thread")
     ("no-cleanup", po::bool_switch(&no_cleanup), "Disable cleanup of files")
     ("json", po::value<string>(&config.json_path), "Output results to a JSON file")
-    ("duration", po::value<int>(&config.duration)->default_value(0), "Limit each phase to N seconds (0 = no limit)");
+    ("duration", po::value<int>(&config.duration)->default_value(0), "Limit each phase to N seconds (0 = no limit)")
+    ("perf-dump", po::value<string>(&config.perf_dump_path), "File to dump performance counters to");
 
   // Hidden positional option for the sub-command
   po::options_description hidden("Hidden options");