[glib/halfline/debug-metrics: 6/12] gobject: Add debug metrics for gnome-shell
- From: Ray Strode <halfline src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/halfline/debug-metrics: 6/12] gobject: Add debug metrics for gnome-shell
- Date: Tue, 21 Dec 2021 17:45:10 +0000 (UTC)
commit 402abd8be60c8502c5ab174c859d52c4985bf1c1
Author: Ray Strode <rstrode redhat com>
Date: Wed May 26 23:47:11 2021 -0400
gobject: Add debug metrics for gnome-shell
gobject/gobject.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 128 insertions(+), 3 deletions(-)
---
diff --git a/gobject/gobject.c b/gobject/gobject.c
index d67987437..46bd4f609 100644
--- a/gobject/gobject.c
+++ b/gobject/gobject.c
@@ -23,6 +23,7 @@
#include <string.h>
#include <signal.h>
+#include <malloc.h>
#include "gobject.h"
#include "gtype-private.h"
@@ -317,7 +318,8 @@ g_object_notify_queue_add (GObject *object,
#ifdef G_ENABLE_DEBUG
G_LOCK_DEFINE_STATIC (debug_objects);
-static guint debug_objects_count = 0;
+static gulong debug_objects_count = 0;
+static gulong debug_objects_watermark = 0;
static GHashTable *debug_objects_ht = NULL;
static void
@@ -340,17 +342,112 @@ debug_objects_foreach (gpointer key,
G_DEFINE_DESTRUCTOR(debug_objects_atexit)
#endif /* G_HAS_CONSTRUCTORS */
+typedef struct _GTypeMetrics GTypeMetrics;
+struct _GTypeMetrics {
+ long instance_count;
+ long instance_change;
+ long instance_watermark;
+};
+
+static GMetricsFile *objects_by_type_metrics_file;
+static GMetricsFile *object_totals_metrics_file;
+static GMetricsInstanceCounter *instance_counter = NULL;
+
static void
debug_objects_atexit (void)
{
GOBJECT_IF_DEBUG (OBJECTS,
{
G_LOCK (debug_objects);
- g_message ("stale GObjects: %u", debug_objects_count);
- g_hash_table_foreach (debug_objects_ht, debug_objects_foreach, NULL);
+ g_message ("stale GObjects: %lu", debug_objects_count);
+ if (debug_objects_ht)
+ {
+ g_hash_table_foreach (debug_objects_ht, debug_objects_foreach, NULL);
+ g_clear_pointer (&debug_objects_ht, g_hash_table_unref);
+ }
G_UNLOCK (debug_objects);
});
}
+
+static void
+on_object_metrics_timeout (void)
+{
+ static gulong old_debug_objects_count = 0;
+
+ if (_g_type_debug_flags & G_TYPE_DEBUG_OBJECTS)
+ {
+ gpointer object;
+ long change;
+
+ if (instance_counter == NULL)
+ instance_counter = g_metrics_instance_counter_new ();
+
+ g_metrics_instance_counter_start_record (instance_counter);
+
+ malloc_trim(0);
+
+ G_LOCK (debug_objects);
+ change = debug_objects_count - old_debug_objects_count;
+ old_debug_objects_count = debug_objects_count;
+
+ if (object_totals_metrics_file)
+ {
+ g_metrics_file_start_record (object_totals_metrics_file);
+ g_metrics_file_add_row (object_totals_metrics_file,
+ (gpointer) debug_objects_count,
+ change > 0? "+" : "",
+ change,
+ debug_objects_watermark);
+ g_metrics_file_end_record (object_totals_metrics_file);
+ }
+
+ if (objects_by_type_metrics_file)
+ {
+ GHashTableIter iter;
+ g_hash_table_iter_init (&iter, debug_objects_ht);
+ while (g_hash_table_iter_next (&iter, NULL, &object))
+ {
+ GType type;
+ GTypeQuery query = { 0 };
+
+ if (!G_IS_OBJECT (object))
+ continue;
+
+ type = G_OBJECT_TYPE (object);
+ g_type_query (type, &query);
+
+ if (query.type != type)
+ continue;
+
+ g_metrics_instance_counter_add_instance (instance_counter, query.type_name,
query.instance_size);
+ }
+ g_metrics_instance_counter_end_record (instance_counter);
+ }
+ G_UNLOCK (debug_objects);
+
+ if (objects_by_type_metrics_file)
+ {
+ GMetricsInstanceCounterIter iter;
+ GMetricsInstanceCounterMetrics *metrics;
+ const char *name = NULL;
+
+ g_metrics_file_start_record (objects_by_type_metrics_file);
+ g_metrics_instance_counter_iter_init (&iter, instance_counter);
+ while (g_metrics_instance_counter_iter_next (&iter, &name, &metrics))
+ {
+ g_metrics_file_add_row (objects_by_type_metrics_file,
+ name,
+ metrics->instance_count,
+ metrics->instance_change > 0? "+" : "",
+ metrics->instance_change,
+ metrics->average_instance_change > 0? "+" : "",
+ metrics->average_instance_change,
+ metrics->instance_watermark);
+ }
+ g_metrics_file_end_record (objects_by_type_metrics_file);
+ }
+ };
+}
#endif /* G_ENABLE_DEBUG */
void
@@ -383,6 +480,9 @@ _g_object_type_init (void)
g_value_object_lcopy_value, /* lcopy_value */
};
GType type;
+#if G_ENABLE_DEBUG
+ gboolean needs_object_metrics = FALSE, needs_object_totals = FALSE;
+#endif
g_return_if_fail (initialized == FALSE);
initialized = TRUE;
@@ -395,6 +495,12 @@ _g_object_type_init (void)
g_value_register_transform_func (G_TYPE_OBJECT, G_TYPE_OBJECT, g_value_object_transform_value);
#if G_ENABLE_DEBUG
+ needs_object_metrics = g_metrics_requested ("objects-by-type");
+ needs_object_totals = g_metrics_requested ("object-totals");
+
+ if (needs_object_metrics || needs_object_totals)
+ _g_type_debug_flags |= G_TYPE_DEBUG_OBJECTS;
+
/* We cannot use GOBJECT_IF_DEBUG here because of the G_HAS_CONSTRUCTORS
* conditional in between, as the C spec leaves conditionals inside macro
* expansions as undefined behavior. Only GCC and Clang are known to work
@@ -408,6 +514,24 @@ _g_object_type_init (void)
# ifndef G_HAS_CONSTRUCTORS
g_atexit (debug_objects_atexit);
# endif /* G_HAS_CONSTRUCTORS */
+
+ if (needs_object_metrics)
+ objects_by_type_metrics_file = g_metrics_file_new ("objects-by-type",
+ "name", "%s",
+ "count", "%ld",
+ "change", "%s%ld",
+ "average change", "%s%ld",
+ "max seen", "%lu",
+ NULL);
+
+ if (needs_object_totals)
+ object_totals_metrics_file = g_metrics_file_new ("object-totals",
+ "count", "%ld",
+ "change", "%s%ld",
+ "max seen", "%lu",
+ NULL);
+ if (needs_object_totals || needs_object_metrics)
+ g_metrics_start_timeout (on_object_metrics_timeout);
}
#endif /* G_ENABLE_DEBUG */
}
@@ -1009,6 +1133,7 @@ g_object_init (GObject *object,
{
G_LOCK (debug_objects);
debug_objects_count++;
+ debug_objects_watermark = MAX (debug_objects_count, debug_objects_watermark);
g_hash_table_add (debug_objects_ht, object);
G_UNLOCK (debug_objects);
});
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]