summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay Strode <rstrode@redhat.com>2021-07-01 16:40:37 -0400
committerRay Strode <rstrode@redhat.com>2023-04-12 14:09:20 -0400
commit0d0f70792e17949beadfef3d51cbcb86730f5780 (patch)
tree1062742cdbb293f16f4d3919cc896d39e7badf24
parentdbd50f23db3304be4509f91b68e6ed2be752247d (diff)
downloadglib-0d0f70792e17949beadfef3d51cbcb86730f5780.tar.gz
garray: track array allocations
-rw-r--r--glib/garray.c235
1 files 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;