diff options
author | Ray Strode <rstrode@redhat.com> | 2021-07-01 16:40:37 -0400 |
---|---|---|
committer | Ray Strode <rstrode@redhat.com> | 2023-04-12 14:09:20 -0400 |
commit | 0d0f70792e17949beadfef3d51cbcb86730f5780 (patch) | |
tree | 1062742cdbb293f16f4d3919cc896d39e7badf24 | |
parent | dbd50f23db3304be4509f91b68e6ed2be752247d (diff) | |
download | glib-0d0f70792e17949beadfef3d51cbcb86730f5780.tar.gz |
garray: track array allocations
-rw-r--r-- | glib/garray.c | 235 |
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; |