[gjs: 5/7] profiler: Define sysprof counters for the GObject wrapper counts




commit 8879b6bc258a08bd5cbc0ba43eb2d6b375d40ca4
Author: Philip Chimento <philip endlessm com>
Date:   Fri Dec 6 16:35:42 2019 -0800

    profiler: Define sysprof counters for the GObject wrapper counts
    
    This sends the current values of the counts from mem.cpp to sysprof along
    with every profiler sample.

 gjs/mem-private.h | 26 +++++++++++++++++++++++++
 gjs/profiler.cpp  | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 83 insertions(+), 1 deletion(-)
---
diff --git a/gjs/mem-private.h b/gjs/mem-private.h
index 8c6caca5..adb07ad6 100644
--- a/gjs/mem-private.h
+++ b/gjs/mem-private.h
@@ -6,6 +6,8 @@
 #ifndef GJS_MEM_PRIVATE_H_
 #define GJS_MEM_PRIVATE_H_
 
+#include <stddef.h>  // for size_t
+
 #include <atomic>
 
 // clang-format off
@@ -59,6 +61,30 @@ constexpr void dec() {
 }  // namespace Memory
 }  // namespace Gjs
 
+#define COUNT(name, ix) +1
+static constexpr size_t GJS_N_COUNTERS = 0 GJS_FOR_EACH_COUNTER(COUNT);
+#undef COUNT
+
+static constexpr const char GJS_COUNTER_DESCRIPTIONS[GJS_N_COUNTERS][52] = {
+    // max length of description string ---------------v
+    "Number of boxed type wrapper objects",
+    "Number of boxed type prototype objects",
+    "Number of signal handlers",
+    "Number of introspected functions",
+    "Number of fundamental type wrapper objects",
+    "Number of fundamental type prototype objects",
+    "Number of GError wrapper objects",
+    "Number of GError prototype objects",
+    "Number of GObject interface objects",
+    "Number of modules",
+    "Number of GI namespace objects",
+    "Number of GObject wrapper objects",
+    "Number of GObject prototype objects",
+    "Number of GParamSpec wrapper objects",
+    "Number of C union wrapper objects",
+    "Number of C union prototype objects",
+};
+
 #define GJS_INC_COUNTER(name) \
     (Gjs::Memory::Counters::inc<&Gjs::Memory::Counters::name>());
 
diff --git a/gjs/profiler.cpp b/gjs/profiler.cpp
index 2d342498..c4518bfa 100644
--- a/gjs/profiler.cpp
+++ b/gjs/profiler.cpp
@@ -34,6 +34,7 @@
 
 #include "gjs/context.h"
 #include "gjs/jsapi-util.h"
+#include "gjs/mem-private.h"
 #include "gjs/profiler.h"
 
 #define FLUSH_DELAY_SECONDS 3
@@ -104,6 +105,7 @@ struct _GjsProfiler {
 
     /* GLib signal handler ID for SIGUSR2 */
     unsigned sigusr2_id;
+    unsigned counter_base;  // index of first GObject memory counter
 #endif  /* ENABLE_PROFILER */
 
     /* If we are currently sampling */
@@ -164,6 +166,38 @@ static GjsContext *profiling_context;
 
     return true;
 }
+
+static void setup_counter_helper(SysprofCaptureCounter* counter,
+                                 const char* counter_name,
+                                 unsigned counter_base, size_t ix) {
+    g_snprintf(counter->category, sizeof counter->category, "GJS");
+    g_snprintf(counter->name, sizeof counter->name, "%s", counter_name);
+    g_snprintf(counter->description, sizeof counter->description, "%s",
+               GJS_COUNTER_DESCRIPTIONS[ix]);
+    counter->id = uint32_t(counter_base + ix);
+    counter->type = SYSPROF_CAPTURE_COUNTER_INT64;
+    counter->value.v64 = 0;
+}
+
+[[nodiscard]] static bool gjs_profiler_define_counters(GjsProfiler* self) {
+    int64_t now = g_get_monotonic_time() * 1000L;
+
+    g_assert(self && "Profiler must be set up before defining counters");
+
+    SysprofCaptureCounter counters[GJS_N_COUNTERS];
+    self->counter_base =
+        sysprof_capture_writer_request_counter(self->capture, GJS_N_COUNTERS);
+
+#    define SETUP_COUNTER(counter_name, ix)                                    \
+        setup_counter_helper(&counters[ix], #counter_name, self->counter_base, \
+                             ix);
+    GJS_FOR_EACH_COUNTER(SETUP_COUNTER);
+#    undef SETUP_COUNTER
+
+    return sysprof_capture_writer_define_counters(
+        self->capture, now, -1, self->pid, counters, GJS_N_COUNTERS);
+}
+
 #endif  /* ENABLE_PROFILER */
 
 /*
@@ -364,7 +398,22 @@ static void gjs_profiler_sigprof(int signum [[maybe_unused]], siginfo_t* info,
     }
 
     if (!sysprof_capture_writer_add_sample(self->capture, now, -1, self->pid,
-                                           -1, addrs, depth))
+                                           -1, addrs, depth)) {
+        gjs_profiler_stop(self);
+        return;
+    }
+
+    unsigned ids[GJS_N_COUNTERS];
+    SysprofCaptureCounterValue values[GJS_N_COUNTERS];
+
+#    define FETCH_COUNTERS(name, ix)       \
+        ids[ix] = self->counter_base + ix; \
+        values[ix].v64 = GJS_GET_COUNTER(name);
+    GJS_FOR_EACH_COUNTER(FETCH_COUNTERS);
+#    undef FETCH_COUNTERS
+
+    if (!sysprof_capture_writer_set_counters(self->capture, now, -1, self->pid,
+                                             ids, values, GJS_N_COUNTERS))
         gjs_profiler_stop(self);
 }
 
@@ -451,6 +500,13 @@ gjs_profiler_start(GjsProfiler *self)
         return;
     }
 
+    if (!gjs_profiler_define_counters(self)) {
+        g_warning("Failed to define sysprof counters");
+        g_clear_pointer(&self->capture, sysprof_capture_writer_unref);
+        g_clear_pointer(&self->periodic_flush, g_source_destroy);
+        return;
+    }
+
     /* Setup our signal handler for SIGPROF delivery */
     sa.sa_flags = SA_RESTART | SA_SIGINFO;
     sa.sa_sigaction = gjs_profiler_sigprof;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]