[glib/halfline/debug-metrics: 6/9] gmain: 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/9] gmain: Add debug metrics for gnome-shell
- Date: Tue, 13 Jul 2021 04:35:41 +0000 (UTC)
commit a6c4c57ada56a1cbcecd4e5629a1fef645f799a6
Author: Ray Strode <rstrode redhat com>
Date: Wed May 26 23:47:11 2021 -0400
gmain: Add debug metrics for gnome-shell
glib/ghash.c | 4 +-
glib/gmain.c | 383 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
glib/gslice.c | 135 ++++++++++++++++++++-
glib/gslice.h | 40 +++++-
4 files changed, 554 insertions(+), 8 deletions(-)
---
diff --git a/glib/ghash.c b/glib/ghash.c
index 3e889001a..c6febe180 100644
--- a/glib/ghash.c
+++ b/glib/ghash.c
@@ -796,7 +796,7 @@ g_hash_table_new_full (GHashFunc hash_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);
+ hash_table = g_new0 (GHashTable, 1);
g_hash_table_set_shift (hash_table, HASH_TABLE_MIN_SHIFT);
hash_table->nnodes = 0;
hash_table->last_sweep = 0;
@@ -1231,7 +1231,7 @@ g_hash_table_unref (GHashTable *hash_table)
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);
+ g_free (hash_table);
}
}
diff --git a/glib/gmain.c b/glib/gmain.c
index 2f4f578d1..3a1ecc639 100644
--- a/glib/gmain.c
+++ b/glib/gmain.c
@@ -606,6 +606,330 @@ g_main_context_new_with_next_id (guint next_id)
return ret;
}
+typedef struct _GSourceMetrics GSourceMetrics;
+struct _GSourceMetrics {
+ long instance_count;
+ long instance_change;
+};
+static GMetricsTable *histograms[2] = { NULL };
+static int old_histogram_index = 0;
+static GMetricsTable *old_histogram = NULL;
+
+static gint
+metrics_sort (GSourceMetrics *a, GSourceMetrics *b)
+{
+ return b->instance_count - a->instance_count;
+}
+
+static GMetricsFile *total_sources_metrics_file;
+static GMetricsFile *sources_metrics_file;
+static GMetricsFile *memory_metrics_file;
+static GMetricsFile *slice_metrics_file;
+static long old_total_sources = 0;
+
+static gboolean
+fetch_current_memory_stats (char **vm_rss,
+ char **vm_data,
+ char **rss_anon,
+ char **vm_hwm,
+ char **vm_size,
+ char **vm_peak,
+ char **rss_file,
+ char **rss_shmem,
+ char **threads,
+ char **fd_size)
+{
+ char *status_contents;
+ gsize length;
+ gboolean got_contents;
+ GString *line_buffer;
+ gsize i;
+
+ /* gdb attach regularly so if customer gdb attaches later they don't see a jump
+ * in memory from things faulting in suddenly
+ */
+ char *command = g_strdup_printf ("gdb --pid=%d --batch", getpid ());
+ system (command);
+ g_free (command);
+
+ got_contents = g_file_get_contents ("/proc/self/status",
+ &status_contents,
+ &length,
+ NULL);
+
+ if (!got_contents)
+ return FALSE;
+
+ line_buffer = g_string_new ("");
+ for (i = 0; i <= length; i++)
+ {
+ char **key_and_value;
+ const char *key;
+ char *value;
+ if (i != length && status_contents[i] != '\n')
+ {
+ g_string_append_c (line_buffer, status_contents[i]);
+ continue;
+ }
+
+ key_and_value = g_strsplit (line_buffer->str, ":", 2);
+ g_string_set_size (line_buffer, 0);
+
+ key = key_and_value[0];
+
+ if (key == NULL)
+ {
+ g_strfreev (key_and_value);
+ continue;
+ }
+
+ value = g_strdup (g_strchug (key_and_value[1]));
+
+ if (strcmp (key, "VmRSS") == 0)
+ *vm_rss = value;
+ else if (strcmp (key, "VmData") == 0)
+ *vm_data = value;
+ else if (strcmp (key, "RssAnon") == 0)
+ *rss_anon = value;
+ else if (strcmp (key, "VmHWM") == 0)
+ *vm_hwm = value;
+ else if (strcmp (key, "VmSize") == 0)
+ *vm_size = value;
+ else if (strcmp (key, "VmPeak") == 0)
+ *vm_peak = value;
+ else if (strcmp (key, "RssFile") == 0)
+ *rss_file = value;
+ else if (strcmp (key, "RssShmem") == 0)
+ *rss_shmem = value;
+ else if (strcmp (key, "Threads") == 0)
+ *threads = value;
+ else if (strcmp (key, "FDSize") == 0)
+ *fd_size = value;
+ else
+ g_free (value);
+
+ g_strfreev (key_and_value);
+ }
+ g_string_free (line_buffer, TRUE);
+
+ g_free (status_contents);
+
+ return TRUE;
+}
+
+static void
+on_metrics_timeout (void)
+{
+ GMetricsTable *histogram;
+ guint new_histogram_index = (old_histogram_index + 1) % G_N_ELEMENTS (histograms);
+ GSList *context_node;
+ long new_total_sources = 0;
+ long change;
+
+ if (memory_metrics_file)
+ {
+ char *vm_rss = NULL;
+ char *vm_data = NULL;
+ char *rss_anon = NULL;
+ char *vm_hwm = NULL;
+ char *vm_size = NULL;
+ char *vm_peak = NULL;
+ char *rss_file = NULL;
+ char *rss_shmem = NULL;
+ char *threads = NULL;
+ char *fd_size = NULL;
+ gsize slice_allocated = 0;
+
+ slice_allocated = g_slice_get_total_allocated_memory ();
+
+ g_metrics_file_start_record (memory_metrics_file);
+ if (fetch_current_memory_stats (&vm_rss,
+ &vm_data,
+ &rss_anon,
+ &vm_hwm,
+ &vm_size,
+ &vm_peak,
+ &rss_file,
+ &rss_shmem,
+ &threads,
+ &fd_size))
+ {
+ g_metrics_file_add_row (memory_metrics_file,
+ vm_rss? : "",
+ vm_data? : "",
+ rss_anon? : "",
+ vm_hwm? : "",
+ slice_allocated,
+ vm_size? : "",
+ vm_peak? : "",
+ rss_file? : "",
+ rss_shmem? : "",
+ threads? : "",
+ fd_size? : "");
+ g_free (vm_rss);
+ g_free (vm_data);
+ g_free (rss_anon);
+ g_free (vm_hwm);
+ g_free (vm_size);
+ g_free (vm_peak);
+ g_free (rss_file);
+ g_free (rss_shmem);
+ g_free (threads);
+ g_free (fd_size);
+ }
+ g_metrics_file_end_record (memory_metrics_file);
+ }
+
+ if (slice_metrics_file)
+ {
+ GMetricsTable *slice_metrics_table;
+ GMetricsTableIter iter;
+ GSliceMetrics *slice_metrics;
+ const char *name;
+
+ g_metrics_file_start_record (slice_metrics_file);
+ slice_metrics_table = g_slice_lock_metrics_table ();
+ g_metrics_table_iter_init (&iter, slice_metrics_table);
+ while (g_metrics_table_iter_next (&iter, &name, &slice_metrics))
+ g_metrics_file_add_row (slice_metrics_file,
+ name,
+ slice_metrics->total_usage,
+ slice_metrics->number_of_allocations);
+ g_slice_unlock_metrics_table ();
+ g_metrics_file_end_record (slice_metrics_file);
+ }
+
+ G_LOCK (main_context_list);
+
+ old_histogram = histograms[old_histogram_index];
+ if (histograms[new_histogram_index] == NULL)
+ histograms[new_histogram_index] = g_metrics_table_new (sizeof (GSourceMetrics));
+
+ histogram = histograms[new_histogram_index];
+ g_metrics_table_clear (histogram);
+
+ for (context_node = main_context_list; context_node != NULL; context_node = context_node->next)
+ {
+ GMainContext *context = context_node->data;
+ GHashTableIter iter;
+ gpointer value;
+
+ if (!context)
+ continue;
+
+ LOCK_CONTEXT (context);
+ g_hash_table_iter_init (&iter, context->sources);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
+ {
+ GSource *source = value;
+ char *name;
+ GSourceMetrics *old_metrics = NULL;
+ GSourceMetrics *metrics;
+ long old_instance_count = 0;
+
+ if (SOURCE_DESTROYED (source))
+ continue;
+
+ if (total_sources_metrics_file)
+ new_total_sources++;
+ name = g_strdup (g_source_get_name (source));
+
+ if (name == NULL)
+ name = g_strdup_printf ("%p", source);
+
+ if (old_histogram != NULL)
+ {
+ old_metrics = g_metrics_table_get_record (old_histogram, name);
+
+ if (old_metrics != NULL)
+ old_instance_count = old_metrics->instance_count;
+ }
+
+ metrics = g_metrics_table_get_record (histogram, name);
+ if (metrics == NULL)
+ {
+ GSourceMetrics new_metrics = { 0 };
+ g_metrics_table_set_record (histogram, name, &new_metrics);
+
+ metrics = g_metrics_table_get_record (histogram, name);
+ }
+
+ g_free (name);
+
+ metrics->instance_count++;
+ metrics->instance_change = metrics->instance_count - old_instance_count;
+ }
+ UNLOCK_CONTEXT (context);
+ }
+
+ if (total_sources_metrics_file)
+ {
+ change = new_total_sources - old_total_sources;
+
+ g_metrics_file_start_record (total_sources_metrics_file);
+ g_metrics_file_add_row (total_sources_metrics_file,
+ (gpointer) new_total_sources,
+ change);
+ g_metrics_file_end_record (total_sources_metrics_file);
+ old_total_sources = new_total_sources;
+ }
+
+ if (old_histogram != NULL)
+ {
+ GMetricsTableIter iter;
+ GSourceMetrics *old_metrics = NULL;
+ const char *old_name = NULL;
+
+ g_metrics_table_iter_init (&iter, old_histogram);
+ while (g_metrics_table_iter_next (&iter, &old_name, &old_metrics))
+ {
+ GSourceMetrics *metrics;
+
+ metrics = g_metrics_table_get_record (histogram, old_name);
+ if (metrics == NULL)
+ {
+ GSourceMetrics new_metrics = { 0 };
+ new_metrics.instance_change = -old_metrics->instance_count;
+ g_metrics_table_set_record (histogram, old_name, &new_metrics);
+ }
+ }
+ }
+
+ if (sources_metrics_file)
+ {
+ GMetricsTableIter iter;
+ GSourceMetrics *metrics = NULL;
+ const char *name = NULL;
+
+ g_metrics_file_start_record (sources_metrics_file);
+ g_metrics_table_sorted_iter_init (&iter, histogram, (GCompareFunc) metrics_sort);
+ while (g_metrics_table_iter_next (&iter, &name, &metrics))
+ {
+ if (metrics->instance_change == 0)
+ continue;
+
+ g_metrics_file_add_row (sources_metrics_file,
+ name,
+ metrics->instance_count,
+ metrics->instance_change > 0? "+" : "",
+ metrics->instance_change);
+ }
+ g_metrics_file_end_record (sources_metrics_file);
+ }
+ if (old_histogram != NULL)
+ g_metrics_table_clear (old_histogram);
+ old_histogram_index = new_histogram_index;
+
+ G_UNLOCK (main_context_list);
+}
+
+static gboolean
+on_timeout_fd_ready (void)
+{
+ g_metrics_run_timeout_handlers ();
+ return G_SOURCE_CONTINUE;
+}
+
/**
* g_main_context_new:
*
@@ -618,6 +942,8 @@ g_main_context_new (void)
{
static gsize initialised;
GMainContext *context;
+ GSource *metrics_timeout_source = NULL;
+ gboolean needs_event_loop_metrics = FALSE, needs_event_loop_totals_metrics = FALSE, needs_mem_metrics =
FALSE, needs_slice_metrics = FALSE;
if (g_once_init_enter (&initialised))
{
@@ -660,6 +986,57 @@ g_main_context_new (void)
g_main_context_add_poll_unlocked (context, 0, &context->wake_up_rec);
G_LOCK (main_context_list);
+
+ if (main_context_list == NULL)
+ {
+ if (g_metrics_enabled ())
+ {
+ int timeout_fd = g_metrics_get_timeout_fd ();
+ metrics_timeout_source = g_unix_fd_source_new (timeout_fd, G_IO_IN);
+ g_source_set_callback (metrics_timeout_source, (GSourceFunc) on_timeout_fd_ready, NULL, NULL);
+ g_source_set_name (metrics_timeout_source, "metrics timeout source");
+ }
+ needs_event_loop_metrics = g_metrics_requested ("event-loop-sources");
+ needs_event_loop_totals_metrics = g_metrics_requested ("event-loop-sources-totals");
+ needs_mem_metrics = g_metrics_requested ("memory-usage");
+ needs_slice_metrics = g_metrics_requested ("slice-memory-usage");
+ }
+
+ if (needs_event_loop_totals_metrics)
+ total_sources_metrics_file = g_metrics_file_new ("event-loop-sources-totals",
+ "total sources", "%ld",
+ "total sources change", "%ld",
+ NULL);
+ if (needs_event_loop_metrics)
+ sources_metrics_file = g_metrics_file_new ("event-loop-sources",
+ "name", "%s",
+ "count", "%ld",
+ "change", "%s%ld",
+ NULL);
+ if (needs_mem_metrics)
+ memory_metrics_file = g_metrics_file_new ("memory-usage",
+ "VmRSS", "%s",
+ "VmData", "%s",
+ "RssAnon", "%s",
+ "VmHWM", "%s",
+ "Slice Allocated", "%ld",
+ "VmSize", "%s",
+ "VmPeak", "%s",
+ "RssFile", "%s",
+ "RssShmem", "%s",
+ "Threads", "%s",
+ "FDSize", "%s",
+ NULL);
+
+ if (needs_slice_metrics)
+ slice_metrics_file = g_metrics_file_new ("slice-memory-usage",
+ "name", "%s",
+ "total-bytes", "%ld",
+ "number of allocations", "%lu",
+ NULL);
+ if (needs_event_loop_metrics || needs_event_loop_totals_metrics || needs_mem_metrics ||
needs_slice_metrics)
+ g_metrics_start_timeout (on_metrics_timeout);
+
main_context_list = g_slist_append (main_context_list, context);
#ifdef G_MAIN_POLL_DEBUG
@@ -669,6 +1046,12 @@ g_main_context_new (void)
G_UNLOCK (main_context_list);
+ if (metrics_timeout_source != NULL)
+ {
+ g_source_attach (metrics_timeout_source, context);
+ g_source_unref (metrics_timeout_source);
+ }
+
return context;
}
diff --git a/glib/gslice.c b/glib/gslice.c
index 454c8a602..c85403108 100644
--- a/glib/gslice.c
+++ b/glib/gslice.c
@@ -391,8 +391,12 @@ slice_config_init (SliceConfig *config)
if (RUNNING_ON_VALGRIND)
config->always_malloc = TRUE;
}
+ config->always_malloc = TRUE;
}
+G_LOCK_DEFINE_STATIC (metrics);
+static GMetricsTable *metrics_table;
+
static void
g_slice_init_nomessage (void)
{
@@ -451,6 +455,11 @@ g_slice_init_nomessage (void)
allocator->max_slab_chunk_size_for_magazine_cache = MAX_SLAB_CHUNK_SIZE (allocator);
if (allocator->config.always_malloc || allocator->config.bypass_magazines)
allocator->max_slab_chunk_size_for_magazine_cache = 0; /* non-optimized cases */
+
+ G_LOCK (metrics);
+ if (g_metrics_requested ("slice-memory-usage"))
+ metrics_table = g_metrics_table_new (sizeof (GSliceMetrics));
+ G_UNLOCK (metrics);
}
static inline guint
@@ -966,6 +975,8 @@ thread_memory_magazine2_free (ThreadMemory *tmem,
*
* Since: 2.10
*/
+#include <gatomic.h>
+static gsize g_slice_allocated_memory = 0;
/**
* g_slice_alloc:
@@ -988,6 +999,17 @@ thread_memory_magazine2_free (ThreadMemory *tmem,
*/
gpointer
g_slice_alloc (gsize mem_size)
+{
+ char *name = g_strdup_printf ("%lu", mem_size);
+ gpointer mem = g_slice_alloc_with_name (mem_size, name);
+ g_free (name);
+
+ return mem;
+}
+
+gpointer
+g_slice_alloc_with_name (gsize mem_size,
+ const char *name)
{
ThreadMemory *tmem;
gsize chunk_size;
@@ -1028,6 +1050,26 @@ g_slice_alloc (gsize mem_size)
TRACE (GLIB_SLICE_ALLOC((void*)mem, mem_size));
+ g_assert (((gssize) mem_size) == mem_size);
+
+ G_LOCK (metrics);
+ if (metrics_table != NULL && mem_size != 0)
+ {
+ GSliceMetrics *metrics = NULL;
+
+ g_slice_allocated_memory += mem_size;
+ metrics = g_metrics_table_get_record (metrics_table, name);
+ if (metrics == NULL)
+ {
+ GSliceMetrics empty_metrics = { 0 };
+ g_metrics_table_set_record (metrics_table, name, &empty_metrics);
+ metrics = g_metrics_table_get_record (metrics_table, name);
+ }
+ metrics->total_usage += mem_size;
+ metrics->number_of_allocations++;
+ }
+ G_UNLOCK (metrics);
+
return mem;
}
@@ -1054,6 +1096,16 @@ g_slice_alloc0 (gsize mem_size)
return mem;
}
+gpointer
+g_slice_alloc0_with_name (gsize mem_size,
+ const char *name)
+{
+ gpointer mem = g_slice_alloc_with_name (mem_size, name);
+ if (mem)
+ memset (mem, 0, mem_size);
+ return mem;
+}
+
/**
* g_slice_copy:
* @block_size: the number of bytes to allocate
@@ -1099,9 +1151,20 @@ g_slice_copy (gsize mem_size,
void
g_slice_free1 (gsize mem_size,
gpointer mem_block)
+{
+ char *name = g_strdup_printf ("%lu", mem_size);
+ g_slice_free1_with_name (mem_size, mem_block, name);
+ g_free (name);
+}
+
+void
+g_slice_free1_with_name (gsize mem_size,
+ gpointer mem_block,
+ const char *name)
{
gsize chunk_size = P2ALIGN (mem_size);
guint acat = allocator_categorize (chunk_size);
+
if (G_UNLIKELY (!mem_block))
return;
if (G_UNLIKELY (allocator->config.debug_blocks) &&
@@ -1136,6 +1199,44 @@ g_slice_free1 (gsize mem_size,
g_free (mem_block);
}
TRACE (GLIB_SLICE_FREE((void*)mem_block, mem_size));
+
+ g_assert (((gssize) mem_size) == mem_size);
+ G_LOCK (metrics);
+ g_slice_allocated_memory -= mem_size;
+ if (metrics_table != NULL)
+ {
+ GSliceMetrics *metrics = NULL;
+
+ metrics = g_metrics_table_get_record (metrics_table, name);
+ if (metrics != NULL)
+ {
+ metrics->total_usage -= mem_size;
+ metrics->number_of_allocations--;
+
+ if (metrics->total_usage <= 0)
+ g_metrics_table_remove_record (metrics_table, name);
+ }
+ }
+ G_UNLOCK (metrics);
+}
+
+gsize
+g_slice_get_total_allocated_memory (void)
+{
+ return g_slice_allocated_memory;
+}
+
+GMetricsTable *
+g_slice_lock_metrics_table (void)
+{
+ G_LOCK (metrics);
+ return metrics_table;
+}
+
+void
+g_slice_unlock_metrics_table (void)
+{
+ G_UNLOCK (metrics);
}
/**
@@ -1163,6 +1264,18 @@ g_slice_free_chain_with_offset (gsize mem_size,
gpointer mem_chain,
gsize next_offset)
{
+ char *name = g_strdup_printf ("%lu", mem_size);
+ g_slice_free_chain_with_offset_and_name (mem_size, mem_chain, next_offset, name);
+ g_free (name);
+}
+
+void
+g_slice_free_chain_with_offset_and_name (gsize mem_size,
+ gpointer mem_chain,
+ gsize next_offset,
+ const char *name)
+{
+ gssize chain_total = 0, chain_length = 0;
gpointer slice = mem_chain;
/* while the thread magazines and the magazine cache are implemented so that
* they can easily be extended to allow for free lists containing more free
@@ -1172,7 +1285,7 @@ g_slice_free_chain_with_offset (gsize mem_size,
* the code adapting to lock contention;
* - freeing a single node to the thread magazines is very fast, so this
* O(list_length) operation is multiplied by a fairly small factor;
- * - memory usage histograms on larger applications seem to indicate that
+ * - memory usage metricss on larger applications seem to indicate that
* the amount of released multi node lists is negligible in comparison
* to single node releases.
* - the major performance bottle neck, namely g_private_get() or
@@ -1229,8 +1342,28 @@ g_slice_free_chain_with_offset (gsize mem_size,
abort();
if (G_UNLIKELY (g_mem_gc_friendly))
memset (current, 0, mem_size);
+ chain_total += mem_size;
+ chain_length++;
g_free (current);
}
+
+ G_LOCK (metrics);
+ g_slice_allocated_memory -= chain_total;
+ if (metrics_table != NULL)
+ {
+ GSliceMetrics *metrics = NULL;
+
+ metrics = g_metrics_table_get_record (metrics_table, name);
+ if (metrics != NULL)
+ {
+ metrics->total_usage -= chain_total;
+ metrics->number_of_allocations -= chain_length;
+
+ if (metrics->total_usage <= 0)
+ g_metrics_table_remove_record (metrics_table, name);
+ }
+ }
+ G_UNLOCK (metrics);
}
/* --- single page allocator --- */
diff --git a/glib/gslice.h b/glib/gslice.h
index 80762761f..45fe04c9f 100644
--- a/glib/gslice.h
+++ b/glib/gslice.h
@@ -22,13 +22,19 @@
#error "Only <glib.h> can be included directly."
#endif
+#include <glib/gmetrics.h>
#include <glib/gtypes.h>
+#include <string.h>
G_BEGIN_DECLS
/* slices - fast allocation/release of small memory blocks
*/
GLIB_AVAILABLE_IN_ALL
+gpointer g_slice_alloc_with_name (gsize block_size, const char *name) G_GNUC_MALLOC
G_GNUC_ALLOC_SIZE(1);
+GLIB_AVAILABLE_IN_ALL
+gpointer g_slice_alloc0_with_name (gsize block_size, const char *name) G_GNUC_MALLOC
G_GNUC_ALLOC_SIZE(1);
+GLIB_AVAILABLE_IN_ALL
gpointer g_slice_alloc (gsize block_size) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
GLIB_AVAILABLE_IN_ALL
gpointer g_slice_alloc0 (gsize block_size) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
@@ -36,14 +42,24 @@ GLIB_AVAILABLE_IN_ALL
gpointer g_slice_copy (gsize block_size,
gconstpointer mem_block) G_GNUC_MALLOC G_GNUC_ALLOC_SIZE(1);
GLIB_AVAILABLE_IN_ALL
+void g_slice_free1_with_name (gsize block_size,
+ gpointer mem_block,
+ const char *name);
+GLIB_AVAILABLE_IN_ALL
void g_slice_free1 (gsize block_size,
gpointer mem_block);
GLIB_AVAILABLE_IN_ALL
+void g_slice_free_chain_with_offset_and_name (gsize block_size,
+ gpointer mem_chain,
+ gsize next_offset,
+ const char *name);
+GLIB_AVAILABLE_IN_ALL
void g_slice_free_chain_with_offset (gsize block_size,
gpointer mem_chain,
gsize next_offset);
-#define g_slice_new(type) ((type*) g_slice_alloc (sizeof (type)))
-#define g_slice_new0(type) ((type*) g_slice_alloc0 (sizeof (type)))
+#define g_slice_new(type) ((type*) g_slice_alloc_with_name (sizeof (type), #type))
+#define g_slice_new0(type) ((type*) g_slice_alloc0_with_name (sizeof (type), #type))
+
/* MemoryBlockType *
* g_slice_dup (MemoryBlockType,
* MemoryBlockType *mem_block);
@@ -62,13 +78,13 @@ void g_slice_free_chain_with_offset (gsize block_size,
: ((void) ((type*) 0 == (mem)), (type*) 0))
#define g_slice_free(type, mem) \
G_STMT_START { \
- if (1) g_slice_free1 (sizeof (type), (mem)); \
+ if (1) g_slice_free1_with_name (sizeof (type), (mem), #type); \
else (void) ((type*) 0 == (mem)); \
} G_STMT_END
#define g_slice_free_chain(type, mem_chain, next) \
G_STMT_START { \
- if (1) g_slice_free_chain_with_offset (sizeof (type), \
- (mem_chain), G_STRUCT_OFFSET (type, next)); \
+ if (1) g_slice_free_chain_with_offset_and_name (sizeof (type), \
+ (mem_chain), G_STRUCT_OFFSET (type, next), #type); \
else (void) ((type*) 0 == (mem_chain)); \
} G_STMT_END
@@ -89,6 +105,20 @@ gint64 g_slice_get_config (GSliceConfig ckey);
GLIB_DEPRECATED_IN_2_34
gint64* g_slice_get_config_state (GSliceConfig ckey, gint64 address, guint *n_values);
+GLIB_AVAILABLE_IN_ALL
+gsize g_slice_get_total_allocated_memory (void);
+
+typedef struct _GSliceMetrics
+{
+ gssize total_usage;
+ gsize number_of_allocations;
+} GSliceMetrics;
+
+GLIB_AVAILABLE_IN_ALL
+GMetricsTable *g_slice_lock_metrics_table (void);
+GLIB_AVAILABLE_IN_ALL
+void g_slice_unlock_metrics_table (void);
+
#ifdef G_ENABLE_DEBUG
GLIB_AVAILABLE_IN_ALL
void g_slice_debug_tree_statistics (void);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]