[glib/halfline/debug-metrics: 2/9] ghash: Add debug metrics for gnome-shell




commit 06b91a34dca40ecd78dbcd77fd1a1a27b77f2cd3
Author: Ray Strode <rstrode redhat com>
Date:   Wed May 26 23:04:46 2021 -0400

    ghash: Add debug metrics for gnome-shell

 glib/ghash.c          | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++
 glib/ghook.c          |   2 +-
 glib/gmetrics.c       |   2 +-
 glib/gslice.c         |   3 +-
 glib/gtestutils.c     |   3 +-
 glib/gvariant.c       |   7 +--
 glib/gvarianttype.c   |   3 +-
 gobject/gsignal.c     |   3 +-
 gobject/gtype.c       |   9 ++--
 gobject/gtypemodule.c |   3 +-
 10 files changed, 137 insertions(+), 14 deletions(-)
---
diff --git a/glib/ghash.c b/glib/ghash.c
index 131d4ab99..03aaa8044 100644
--- a/glib/ghash.c
+++ b/glib/ghash.c
@@ -238,6 +238,7 @@ struct _GHashTable
 #endif
   GDestroyNotify   key_destroy_func;
   GDestroyNotify   value_destroy_func;
+  gulong           last_sweep;
 };
 
 typedef struct
@@ -253,6 +254,9 @@ typedef struct
 G_STATIC_ASSERT (sizeof (GHashTableIter) == sizeof (RealIter));
 G_STATIC_ASSERT (_g_alignof (GHashTableIter) >= _g_alignof (RealIter));
 
+G_LOCK_DEFINE_STATIC (hash_tables);
+static GMetricsList *hash_tables_list = NULL;
+
 /* Each table size has an associated prime modulo (the first prime
  * lower than the table size) used to find the initial bucket. Probing
  * then works modulo 2^n. The prime modulo is necessary to get a
@@ -680,6 +684,76 @@ g_hash_table_new (GHashFunc  hash_func,
   return g_hash_table_new_full (hash_func, key_equal_func, NULL, NULL);
 }
 
+static GMetricsFile *metrics_file;
+static GMetricsFile *combined_metrics_file;
+static unsigned long old_total_items = 0, old_total_tables;
+
+static void
+on_hash_table_metrics_timeout (void)
+{
+  GHashTable *hash_table;
+  unsigned long new_total_items = 0, new_total_tables = 0;
+  long change, table_change;
+  GMetricsListIter iter;
+
+  if (combined_metrics_file)
+    g_metrics_file_start_record (combined_metrics_file);
+
+  if (metrics_file)
+    g_metrics_file_start_record (metrics_file);
+
+  G_LOCK (hash_tables);
+  g_metrics_list_iter_init (&iter, hash_tables_list);
+  while (g_metrics_list_iter_next (&iter, &hash_table))
+    {
+      glong new_items;
+
+      if (combined_metrics_file)
+        {
+          new_total_items += hash_table->nnodes;
+          new_total_tables++;
+        }
+
+      if (!metrics_file)
+        continue;
+
+      new_items = (glong) hash_table->nnodes - (glong) hash_table->last_sweep;
+      if (new_items != 0)
+        {
+          if (hash_table->last_sweep != 0)
+            g_metrics_file_add_row (metrics_file,
+                                    hash_table,
+                                    hash_table->nnodes,
+                                    new_items > 0 ? "+" : "",
+                                    new_items);
+          hash_table->last_sweep = hash_table->nnodes;
+        }
+    }
+  G_UNLOCK (hash_tables);
+
+  if (metrics_file)
+    g_metrics_file_end_record (metrics_file);
+
+  if (combined_metrics_file)
+    {
+      table_change = new_total_tables - old_total_tables;
+      change = new_total_items - old_total_items;
+
+      g_metrics_file_add_row (combined_metrics_file,
+                              (gpointer) new_total_items,
+                              change > 0? "+" : "",
+                              change,
+                              new_total_tables,
+                              table_change > 0? "+" : "",
+                              table_change);
+      g_metrics_file_end_record (combined_metrics_file);
+    }
+
+  old_total_items = new_total_items;
+  old_total_tables = new_total_tables;
+}
+
+static gboolean metrics_timeout_started;
 
 /**
  * g_hash_table_new_full:
@@ -713,10 +787,12 @@ g_hash_table_new_full (GHashFunc      hash_func,
                        GDestroyNotify value_destroy_func)
 {
   GHashTable *hash_table;
+  gboolean needs_hash_table_metrics = FALSE, needs_hash_table_totals = FALSE;
   HASH_TABLE_MIN_SHIFT = atoi(getenv ("G_HASH_TABLE_MIN_SHIFT")? : "3");
   hash_table = g_slice_new (GHashTable);
   g_hash_table_set_shift (hash_table, HASH_TABLE_MIN_SHIFT);
   hash_table->nnodes             = 0;
+  hash_table->last_sweep         = 0;
   hash_table->noccupied          = 0;
   hash_table->hash_func          = hash_func ? hash_func : g_direct_hash;
   hash_table->key_equal_func     = key_equal_func;
@@ -730,6 +806,42 @@ g_hash_table_new_full (GHashFunc      hash_func,
   hash_table->values             = hash_table->keys;
   hash_table->hashes             = g_new0 (guint, hash_table->size);
 
+  G_LOCK (hash_tables);
+  if (g_metrics_enabled ())
+    {
+      if (hash_tables_list == NULL)
+      {
+          needs_hash_table_metrics = g_metrics_requested ("hash-tables");
+          needs_hash_table_totals = g_metrics_requested ("total-hash-tables");
+          hash_tables_list = g_metrics_list_new ();
+      }
+      g_metrics_list_add_item (hash_tables_list, hash_table);
+    }
+  G_UNLOCK (hash_tables);
+
+  if (!metrics_timeout_started)
+    {
+      metrics_timeout_started = TRUE;
+
+      if (needs_hash_table_metrics)
+        metrics_file = g_metrics_file_new ("hash-tables",
+                                           "address", "%p",
+                                           "total items", "%ld",
+                                           "total items change", "%s%ld",
+                                           NULL);
+
+      if (needs_hash_table_totals)
+        combined_metrics_file = g_metrics_file_new ("total-hash-tables",
+                                                    "total items", "%ld",
+                                                    "total items change", "%s%ld",
+                                                    "total tables", "%ld",
+                                                    "total tables changed", "%s%ld",
+                                                    NULL);
+
+      if (needs_hash_table_metrics || needs_hash_table_totals)
+        g_metrics_start_timeout (on_hash_table_metrics_timeout);
+    }
+
   return hash_table;
 }
 
@@ -1105,6 +1217,10 @@ g_hash_table_unref (GHashTable *hash_table)
         g_free (hash_table->values);
       g_free (hash_table->keys);
       g_free (hash_table->hashes);
+      G_LOCK (hash_tables);
+      if (hash_tables_list != NULL)
+        g_metrics_list_remove_item (hash_tables_list, hash_table);
+      G_UNLOCK (hash_tables);
       g_slice_free (GHashTable, hash_table);
     }
 }
diff --git a/glib/ghook.c b/glib/ghook.c
index 00187bf79..1ddd3e644 100644
--- a/glib/ghook.c
+++ b/glib/ghook.c
@@ -268,7 +268,7 @@ g_hook_alloc (GHookList *hook_list)
   g_return_val_if_fail (hook_list != NULL, NULL);
   g_return_val_if_fail (hook_list->is_setup, NULL);
   
-  hook = g_slice_alloc0 (hook_list->hook_size);
+  hook = g_slice_alloc0_with_name (hook_list->hook_size, "GHook");
   hook->data = NULL;
   hook->next = NULL;
   hook->prev = NULL;
diff --git a/glib/gmetrics.c b/glib/gmetrics.c
index 9c69f2ed7..67e922e45 100644
--- a/glib/gmetrics.c
+++ b/glib/gmetrics.c
@@ -1140,7 +1140,7 @@ g_metrics_file_new (const char *name,
       else
         snprintf (g_metrics_log_dir, sizeof (g_metrics_log_dir) - 1, "%s/metrics/%u", g_get_user_cache_dir 
(), getpid ());
     }
-
+  
   asprintf (&filename,"%s/%s.csv.gz", g_metrics_log_dir, name);
   g_mkdir_with_parents (g_metrics_log_dir, 0755);
 
diff --git a/glib/gslice.c b/glib/gslice.c
index 454c8a602..8e2359515 100644
--- a/glib/gslice.c
+++ b/glib/gslice.c
@@ -45,6 +45,7 @@
 #include "gmain.h"
 #include "gmem.h"               /* gslice.h */
 #include "gstrfuncs.h"
+#include "gstrfuncsprivate.h"
 #include "gutils.h"
 #include "gtrashstack.h"
 #include "gtestutils.h"
@@ -352,7 +353,7 @@ g_slice_get_config_state (GSliceConfig ckey,
       array[i++] = allocator->contention_counters[address];
       array[i++] = allocator_get_magazine_threshold (allocator, address);
       *n_values = i;
-      return g_memdup (array, sizeof (array[0]) * *n_values);
+      return g_memdup2 (array, sizeof (array[0]) * *n_values);
     default:
       return NULL;
     }
diff --git a/glib/gtestutils.c b/glib/gtestutils.c
index 0447dcda5..14e071fce 100644
--- a/glib/gtestutils.c
+++ b/glib/gtestutils.c
@@ -49,6 +49,7 @@
 #include "gpattern.h"
 #include "grand.h"
 #include "gstrfuncs.h"
+#include "gstrfuncsprivate.h"
 #include "gtimer.h"
 #include "gslice.h"
 #include "gspawn.h"
@@ -3397,7 +3398,7 @@ g_test_log_extract (GTestLogBuffer *tbuffer)
       if (p <= tbuffer->data->str + mlength)
         {
           g_string_erase (tbuffer->data, 0, mlength);
-          tbuffer->msgs = g_slist_prepend (tbuffer->msgs, g_memdup (&msg, sizeof (msg)));
+          tbuffer->msgs = g_slist_prepend (tbuffer->msgs, g_memdup2 (&msg, sizeof (msg)));
           return TRUE;
         }
 
diff --git a/glib/gvariant.c b/glib/gvariant.c
index 8be9ce798..45a1a73dc 100644
--- a/glib/gvariant.c
+++ b/glib/gvariant.c
@@ -33,6 +33,7 @@
 
 #include <string.h>
 
+#include "gstrfuncsprivate.h"
 
 /**
  * SECTION:gvariant
@@ -720,7 +721,7 @@ g_variant_new_variant (GVariant *value)
   g_variant_ref_sink (value);
 
   return g_variant_new_from_children (G_VARIANT_TYPE_VARIANT,
-                                      g_memdup (&value, sizeof value),
+                                      g_memdup2 (&value, sizeof value),
                                       1, g_variant_is_trusted (value));
 }
 
@@ -1224,7 +1225,7 @@ g_variant_new_fixed_array (const GVariantType  *element_type,
       return NULL;
     }
 
-  data = g_memdup (elements, n_elements * element_size);
+  data = g_memdup2 (elements, n_elements * element_size);
   value = g_variant_new_from_data (array_type, data,
                                    n_elements * element_size,
                                    FALSE, g_free, data);
@@ -1901,7 +1902,7 @@ g_variant_dup_bytestring (GVariant *value,
   if (length)
     *length = size;
 
-  return g_memdup (original, size + 1);
+  return g_memdup2 (original, size + 1);
 }
 
 /**
diff --git a/glib/gvarianttype.c b/glib/gvarianttype.c
index 9910dee93..7de4202cb 100644
--- a/glib/gvarianttype.c
+++ b/glib/gvarianttype.c
@@ -27,6 +27,7 @@
 
 #include <string.h>
 
+#include "gstrfuncsprivate.h"
 
 /**
  * SECTION:gvarianttype
@@ -1109,7 +1110,7 @@ g_variant_type_new_tuple (const GVariantType * const *items,
   g_assert (offset < sizeof buffer);
   buffer[offset++] = ')';
 
-  return (GVariantType *) g_memdup (buffer, offset);
+  return (GVariantType *) g_memdup2 (buffer, offset);
 }
 
 /**
diff --git a/gobject/gsignal.c b/gobject/gsignal.c
index fa7d9b274..cd5780518 100644
--- a/gobject/gsignal.c
+++ b/gobject/gsignal.c
@@ -28,6 +28,7 @@
 #include <signal.h>
 
 #include "gsignal.h"
+#include "gstrfuncsprivate.h"
 #include "gtype-private.h"
 #include "gbsearcharray.h"
 #include "gvaluecollector.h"
@@ -1724,7 +1725,7 @@ g_signal_newv (const gchar       *signal_name,
   node->single_va_closure_is_valid = FALSE;
   node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
   node->n_params = n_params;
-  node->param_types = g_memdup (param_types, sizeof (GType) * n_params);
+  node->param_types = g_memdup2 (param_types, sizeof (GType) * n_params);
   node->return_type = return_type;
   node->class_closure_bsa = NULL;
   if (accumulator)
diff --git a/gobject/gtype.c b/gobject/gtype.c
index 275a8b60b..9e663ce52 100644
--- a/gobject/gtype.c
+++ b/gobject/gtype.c
@@ -33,6 +33,7 @@
 
 #include "glib-private.h"
 #include "gconstructor.h"
+#include "gstrfuncsprivate.h"
 
 #ifdef G_OS_WIN32
 #include <windows.h>
@@ -1471,7 +1472,7 @@ type_add_interface_Wm (TypeNode             *node,
   iholder->next = iface_node_get_holders_L (iface);
   iface_node_set_holders_W (iface, iholder);
   iholder->instance_type = NODE_TYPE (node);
-  iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL;
+  iholder->info = info ? g_memdup2 (info, sizeof (*info)) : NULL;
   iholder->plugin = plugin;
 
   /* create an iface entry for this type */
@@ -1732,7 +1733,7 @@ type_iface_retrieve_holder_info_Wm (TypeNode *iface,
         INVALID_RECURSION ("g_type_plugin_*", iholder->plugin, NODE_NAME (iface));
       
       check_interface_info_I (iface, instance_type, &tmp_info);
-      iholder->info = g_memdup (&tmp_info, sizeof (tmp_info));
+      iholder->info = g_memdup2 (&tmp_info, sizeof (tmp_info));
     }
   
   return iholder;      /* we don't modify write lock upon returning NULL */
@@ -2013,10 +2014,10 @@ type_iface_vtable_base_init_Wm (TypeNode *iface,
       IFaceEntry *pentry = type_lookup_iface_entry_L (pnode, iface);
       
       if (pentry)
-       vtable = g_memdup (pentry->vtable, iface->data->iface.vtable_size);
+       vtable = g_memdup2 (pentry->vtable, iface->data->iface.vtable_size);
     }
   if (!vtable)
-    vtable = g_memdup (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size);
+    vtable = g_memdup2 (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size);
   entry->vtable = vtable;
   vtable->g_type = NODE_TYPE (iface);
   vtable->g_instance_type = NODE_TYPE (node);
diff --git a/gobject/gtypemodule.c b/gobject/gtypemodule.c
index c67f789b1..cf877bc0b 100644
--- a/gobject/gtypemodule.c
+++ b/gobject/gtypemodule.c
@@ -19,6 +19,7 @@
 
 #include <stdlib.h>
 
+#include "gstrfuncsprivate.h"
 #include "gtypeplugin.h"
 #include "gtypemodule.h"
 
@@ -436,7 +437,7 @@ g_type_module_register_type (GTypeModule     *module,
   module_type_info->loaded = TRUE;
   module_type_info->info = *type_info;
   if (type_info->value_table)
-    module_type_info->info.value_table = g_memdup (type_info->value_table,
+    module_type_info->info.value_table = g_memdup2 (type_info->value_table,
                                                   sizeof (GTypeValueTable));
 
   return module_type_info->type;


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