[glib/halfline/debug-metrics: 10/12] garray: track array allocations




commit e1f80890a8a9459df2486be734597423c18b8d39
Author: Ray Strode <rstrode redhat com>
Date:   Thu Jul 1 16:40:37 2021 -0400

    garray: track array allocations

 glib/garray.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 233 insertions(+), 2 deletions(-)
---
diff --git a/glib/garray.c b/glib/garray.c
index aa3c04707..bc01f805c 100644
--- a/glib/garray.c
+++ b/glib/garray.c
@@ -88,6 +88,8 @@
 #define MIN_ARRAY_SIZE  16
 
 typedef struct _GRealArray  GRealArray;
+G_LOCK_DEFINE_STATIC (arrays);
+static GMetricsList *arrays_list = NULL;
 
 /**
  * GArray:
@@ -107,6 +109,7 @@ struct _GRealArray
   guint   zero_terminated : 1;
   guint   clear : 1;
   gint    ref_count;
+  guint   last_sweep;
   GDestroyNotify clear_func;
 };
 
@@ -165,6 +168,77 @@ g_array_new (gboolean zero_terminated,
   return g_array_sized_new (zero_terminated, clear, elt_size, 0);
 }
 
+static gboolean array_metrics_timeout_started;
+
+static GMetricsFile *array_metrics_file;
+static GMetricsFile *array_combined_metrics_file;
+static unsigned long old_total_array_items = 0, old_total_arrays;
+
+static void
+on_array_metrics_timeout (void)
+{
+  GRealArray *array;
+  unsigned long new_total_items = 0, new_total_arrays = 0;
+  long change, table_change;
+  GMetricsListIter iter;
+
+  if (array_combined_metrics_file)
+    g_metrics_file_start_record (array_combined_metrics_file);
+
+  if (array_metrics_file)
+    g_metrics_file_start_record (array_metrics_file);
+
+  G_LOCK (arrays);
+  g_metrics_list_iter_init (&iter, arrays_list);
+  while (g_metrics_list_iter_next (&iter, &array))
+    {
+      int new_items;
+
+      if (array_combined_metrics_file)
+        {
+          new_total_items += array->len;
+          new_total_arrays++;
+        }
+
+      if (!array_metrics_file)
+        continue;
+
+      new_items = (int) array->len - (int) array->last_sweep;
+      if (new_items != 0)
+        {
+          if (array->last_sweep != 0)
+            g_metrics_file_add_row (array_metrics_file,
+                                    array,
+                                    array->len,
+                                    new_items > 0 ? "+" : "",
+                                    new_items);
+          array->last_sweep = array->len;
+        }
+    }
+  G_UNLOCK (arrays);
+
+  if (array_metrics_file)
+    g_metrics_file_end_record (array_metrics_file);
+
+  if (array_combined_metrics_file)
+    {
+      table_change = new_total_arrays - old_total_arrays;
+      change = new_total_items - old_total_array_items;
+
+      g_metrics_file_add_row (array_combined_metrics_file,
+                              new_total_items,
+                              change > 0? "+" : "",
+                              change,
+                              new_total_arrays,
+                              table_change > 0? "+" : "",
+                              table_change);
+      g_metrics_file_end_record (array_combined_metrics_file);
+    }
+
+  old_total_array_items = new_total_items;
+  old_total_arrays = new_total_arrays;
+}
+
 /**
  * g_array_sized_new:
  * @zero_terminated: %TRUE if the array should have an extra element at
@@ -188,13 +262,51 @@ g_array_sized_new (gboolean zero_terminated,
                    guint    reserved_size)
 {
   GRealArray *array;
+  gboolean needs_array_metrics = FALSE, needs_array_totals = FALSE;
   
   g_return_val_if_fail (elt_size > 0, NULL);
 
   array = g_slice_new (GRealArray);
 
+  G_LOCK (arrays);
+  if (g_metrics_enabled ())
+    {
+      if (arrays_list == NULL)
+        {
+          needs_array_metrics = g_metrics_requested ("arrays");
+          needs_array_totals = g_metrics_requested ("arrays");
+          arrays_list = g_metrics_list_new ();
+       }
+      g_metrics_list_add_item (arrays_list, array);
+    }
+  G_UNLOCK (arrays);
+
+  if (!array_metrics_timeout_started)
+    {
+      array_metrics_timeout_started = TRUE;
+
+      if (needs_array_metrics)
+        array_metrics_file = g_metrics_file_new ("arrays",
+                                                 "address", "%p",
+                                                 "total items", "%ld",
+                                                 "total items change", "%s%d",
+                                                 NULL);
+
+      if (needs_array_totals)
+        array_combined_metrics_file = g_metrics_file_new ("total-arrays",
+                                                          "total items", "%ld",
+                                                          "total items change", "%s%ld",
+                                                          "total arrays", "%ld",
+                                                          "total arrays changed", "%s%d",
+                                                          NULL);
+
+      if (needs_array_metrics || needs_array_totals)
+        g_metrics_start_timeout (on_array_metrics_timeout);
+    }
+
   array->data            = NULL;
   array->len             = 0;
+  array->last_sweep      = 0;
   array->alloc           = 0;
   array->zero_terminated = (zero_terminated ? 1 : 0);
   array->clear           = (clear ? 1 : 0);
@@ -382,7 +494,11 @@ array_free (GRealArray     *array,
     }
   else
     {
-      g_slice_free1 (sizeof (GRealArray), array);
+      G_LOCK (arrays);
+      if (arrays_list)
+        g_metrics_list_remove_item (arrays_list, array);
+      G_UNLOCK (arrays);
+      g_slice_free (GRealArray, array);
     }
 
   return segment;
@@ -864,6 +980,7 @@ struct _GRealPtrArray
   guint           len;
   guint           alloc;
   gint            ref_count;
+  guint           last_sweep;
   GDestroyNotify  element_free_func;
 };
 
@@ -896,6 +1013,78 @@ g_ptr_array_new (void)
   return g_ptr_array_sized_new (0);
 }
 
+static gboolean ptr_array_metrics_timeout_started;
+
+static GMetricsList *ptr_arrays_list = NULL;
+static GMetricsFile *ptr_array_metrics_file;
+static GMetricsFile *ptr_array_combined_metrics_file;
+static unsigned long old_total_ptr_array_items = 0, old_total_ptr_arrays;
+
+static void
+on_ptr_array_metrics_timeout (void)
+{
+  GRealPtrArray *array;
+  unsigned long new_total_items = 0, new_total_ptr_arrays = 0;
+  long change, table_change;
+  GMetricsListIter iter;
+
+  if (ptr_array_combined_metrics_file)
+    g_metrics_file_start_record (ptr_array_combined_metrics_file);
+
+  if (ptr_array_metrics_file)
+    g_metrics_file_start_record (ptr_array_metrics_file);
+
+  G_LOCK (arrays);
+  g_metrics_list_iter_init (&iter, ptr_arrays_list);
+  while (g_metrics_list_iter_next (&iter, &array))
+    {
+      int new_items;
+
+      if (ptr_array_combined_metrics_file)
+        {
+          new_total_items += array->len;
+          new_total_ptr_arrays++;
+        }
+
+      if (!ptr_array_metrics_file)
+        continue;
+
+      new_items = (int) array->len - (int) array->last_sweep;
+      if (new_items != 0)
+        {
+          if (array->last_sweep != 0)
+            g_metrics_file_add_row (ptr_array_metrics_file,
+                                    array,
+                                    array->len,
+                                    new_items > 0 ? "+" : "",
+                                    new_items);
+          array->last_sweep = array->len;
+        }
+    }
+  G_UNLOCK (arrays);
+
+  if (ptr_array_metrics_file)
+    g_metrics_file_end_record (ptr_array_metrics_file);
+
+  if (ptr_array_combined_metrics_file)
+    {
+      table_change = new_total_ptr_arrays - old_total_ptr_arrays;
+      change = new_total_items - old_total_ptr_array_items;
+
+      g_metrics_file_add_row (ptr_array_combined_metrics_file,
+                              new_total_items,
+                              change > 0? "+" : "",
+                              change,
+                              new_total_ptr_arrays,
+                              table_change > 0? "+" : "",
+                              table_change);
+      g_metrics_file_end_record (ptr_array_combined_metrics_file);
+    }
+
+  old_total_ptr_array_items = new_total_items;
+  old_total_ptr_arrays = new_total_ptr_arrays;
+}
+
 /**
  * g_ptr_array_sized_new:
  * @reserved_size: number of pointers preallocated
@@ -911,11 +1100,26 @@ GPtrArray*
 g_ptr_array_sized_new (guint reserved_size)
 {
   GRealPtrArray *array;
+  gboolean needs_ptr_array_metrics = FALSE, needs_ptr_array_totals = FALSE;
 
   array = g_slice_new (GRealPtrArray);
 
+  G_LOCK (arrays);
+  if (g_metrics_enabled ())
+    {
+      if (ptr_arrays_list == NULL)
+        {
+          needs_ptr_array_metrics = g_metrics_requested ("ptr-arrays");
+          needs_ptr_array_totals = g_metrics_requested ("total-ptr-arrays");
+          ptr_arrays_list = g_metrics_list_new ();
+        }
+      g_metrics_list_add_item (ptr_arrays_list, array);
+    }
+  G_UNLOCK (arrays);
+
   array->pdata = NULL;
   array->len = 0;
+  array->last_sweep = 0;
   array->alloc = 0;
   array->ref_count = 1;
   array->element_free_func = NULL;
@@ -923,6 +1127,29 @@ g_ptr_array_sized_new (guint reserved_size)
   if (reserved_size != 0)
     g_ptr_array_maybe_expand (array, reserved_size);
 
+  if (!ptr_array_metrics_timeout_started)
+    {
+      ptr_array_metrics_timeout_started = TRUE;
+
+      if (needs_ptr_array_metrics)
+        ptr_array_metrics_file = g_metrics_file_new ("ptr-arrays",
+                                                     "address", "%p",
+                                                     "total items", "%d",
+                                                     "total items change", "%s%d",
+                                                     NULL);
+
+      if (needs_ptr_array_totals)
+        ptr_array_combined_metrics_file = g_metrics_file_new ("total-ptr-arrays",
+                                                              "total items", "%ld",
+                                                              "total items change", "%s%ld",
+                                                              "total ptr arrays", "%ld",
+                                                              "total ptry arrays changed", "%s%ld",
+                                                              NULL);
+
+      if (needs_ptr_array_metrics || needs_ptr_array_totals)
+        g_metrics_start_timeout (on_ptr_array_metrics_timeout);
+    }
+
   return (GPtrArray*) array;  
 }
 
@@ -1119,7 +1346,11 @@ ptr_array_free (GPtrArray      *array,
     }
   else
     {
-      g_slice_free1 (sizeof (GRealPtrArray), rarray);
+      G_LOCK (arrays);
+      if (ptr_arrays_list)
+        g_metrics_list_remove_item (ptr_arrays_list, rarray);
+      G_UNLOCK (arrays);
+      g_slice_free (GRealPtrArray, rarray);
     }
 
   return segment;


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