From 2e1a6a21dec5ef6eae0d4f4ed4b2b28763179110 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Wed, 22 May 2019 11:24:26 -0700 Subject: [PATCH] libsysprof-ui: teach marks model how to use counters We can use this for an alternate view with counters instead of marks. --- src/libsysprof-ui/sysprof-marks-model.c | 194 ++++++++++++++++++--- src/libsysprof-ui/sysprof-marks-model.h | 35 ++-- src/libsysprof-ui/sysprof-marks-view.c | 21 +++ src/libsysprof-ui/ui/sysprof-marks-view.ui | 2 +- 4 files changed, 215 insertions(+), 37 deletions(-) diff --git a/src/libsysprof-ui/sysprof-marks-model.c b/src/libsysprof-ui/sysprof-marks-model.c index a9e1e3b0..e3f2c213 100644 --- a/src/libsysprof-ui/sysprof-marks-model.c +++ b/src/libsysprof-ui/sysprof-marks-model.c @@ -30,18 +30,28 @@ struct _SysprofMarksModel { GObject parent_instance; GStringChunk *chunks; + GHashTable *counters; GArray *items; gint64 max_end_time; }; typedef struct { - gint64 begin_time; - gint64 end_time; - const gchar *group; - const gchar *name; + gint64 begin_time; + gint64 end_time; + const gchar *group; + const gchar *name; + SysprofCaptureCounterValue value; + guint is_counter : 1; + guint counter_type : 8; } Item; +static void +counter_free (gpointer data) +{ + g_slice_free (SysprofCaptureCounter, data); +} + static gint sysprof_marks_model_get_n_columns (GtkTreeModel *model) { @@ -69,6 +79,9 @@ sysprof_marks_model_get_column_type (GtkTreeModel *model, case SYSPROF_MARKS_MODEL_COLUMN_DURATION: return G_TYPE_DOUBLE; + case SYSPROF_MARKS_MODEL_COLUMN_TEXT: + return G_TYPE_STRING; + default: return 0; } @@ -214,6 +227,25 @@ sysprof_marks_model_get_value (GtkTreeModel *model, g_value_set_double (value, (item->end_time - item->begin_time) / (double)(G_USEC_PER_SEC * 1000)); break; + case SYSPROF_MARKS_MODEL_COLUMN_TEXT: + g_value_init (value, G_TYPE_STRING); + if (item->is_counter) + { + gchar *val = NULL; + + if (item->counter_type == SYSPROF_CAPTURE_COUNTER_DOUBLE) + val = g_strdup_printf ("%s — %s = %.4lf", item->group, item->name, item->value.vdbl); + else if (item->counter_type == SYSPROF_CAPTURE_COUNTER_INT64) + val = g_strdup_printf ("%s — %s = %"G_GINT64_FORMAT, item->group, item->name, item->value.v64); + + g_value_take_string (value, g_steal_pointer (&val)); + } + else + { + g_value_set_string (value, item->name); + } + break; + default: break; } @@ -242,6 +274,7 @@ sysprof_marks_model_finalize (GObject *object) { SysprofMarksModel *self = (SysprofMarksModel *)object; + g_clear_pointer (&self->counters, g_hash_table_unref); g_clear_pointer (&self->items, g_array_unref); g_clear_pointer (&self->chunks, g_string_chunk_free); @@ -259,6 +292,7 @@ sysprof_marks_model_class_init (SysprofMarksModelClass *klass) static void sysprof_marks_model_init (SysprofMarksModel *self) { + self->counters = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, counter_free); self->chunks = g_string_chunk_new (4096*16); self->items = g_array_new (FALSE, FALSE, sizeof (Item)); } @@ -268,21 +302,75 @@ cursor_foreach_cb (const SysprofCaptureFrame *frame, gpointer user_data) { SysprofMarksModel *self = user_data; - SysprofCaptureMark *mark = (SysprofCaptureMark *)frame; Item item; g_assert (SYSPROF_IS_MARKS_MODEL (self)); - g_assert (frame->type == SYSPROF_CAPTURE_FRAME_MARK); + g_assert (frame->type == SYSPROF_CAPTURE_FRAME_MARK || + frame->type == SYSPROF_CAPTURE_FRAME_CTRSET || + frame->type == SYSPROF_CAPTURE_FRAME_CTRDEF); - item.begin_time = frame->time; - item.end_time = item.begin_time + mark->duration; - item.group = g_string_chunk_insert_const (self->chunks, mark->group); - item.name = g_string_chunk_insert_const (self->chunks, mark->name); + if (frame->type == SYSPROF_CAPTURE_FRAME_MARK) + { + SysprofCaptureMark *mark = (SysprofCaptureMark *)frame; - if G_LIKELY (item.end_time > self->max_end_time) - self->max_end_time = item.end_time; + item.begin_time = frame->time; + item.end_time = item.begin_time + mark->duration; + item.group = g_string_chunk_insert_const (self->chunks, mark->group); + item.name = g_string_chunk_insert_const (self->chunks, mark->name); + item.value.v64 = 0; + item.is_counter = FALSE; + item.counter_type = 0; - g_array_append_val (self->items, item); + if G_LIKELY (item.end_time > self->max_end_time) + self->max_end_time = item.end_time; + + g_array_append_val (self->items, item); + } + else if (frame->type == SYSPROF_CAPTURE_FRAME_CTRDEF) + { + SysprofCaptureFrameCounterDefine *ctrdef = (SysprofCaptureFrameCounterDefine *)frame; + + for (guint i = 0; i < ctrdef->n_counters; i++) + { + SysprofCaptureCounter *ctr = &ctrdef->counters[i]; + + g_hash_table_insert (self->counters, + GUINT_TO_POINTER ((guint)ctr->id), + g_slice_dup (SysprofCaptureCounter, ctr)); + } + } + else if (frame->type == SYSPROF_CAPTURE_FRAME_CTRSET) + { + SysprofCaptureFrameCounterSet *ctrset = (SysprofCaptureFrameCounterSet *)frame; + + for (guint i = 0; i < ctrset->n_values; i++) + { + SysprofCaptureCounterValues *values = &ctrset->values[i]; + + for (guint j = 0; j < G_N_ELEMENTS (values->ids); j++) + { + guint32 id = values->ids[j]; + SysprofCaptureCounter *ctr = NULL; + + if (id == 0) + break; + + if ((ctr = g_hash_table_lookup (self->counters, GUINT_TO_POINTER (id)))) + { + item.begin_time = frame->time; + item.end_time = frame->time; + item.group = ctr->category; + item.name = ctr->name; + item.value = values->values[j]; + item.is_counter = TRUE; + item.counter_type = ctr->type; + + g_array_append_val (self->items, item); + } + } + + } + } return TRUE; } @@ -343,20 +431,22 @@ sysprof_marks_model_selection_foreach_cb (SysprofSelection *selection, c = sysprof_capture_condition_new_where_time_between (begin, end); - if (*condition) - *condition = sysprof_capture_condition_new_or (c, *condition); + if (*condition != NULL) + *condition = sysprof_capture_condition_new_or (g_steal_pointer (&c), + g_steal_pointer (condition)); else - *condition = c; + *condition = g_steal_pointer (&c); } void -sysprof_marks_model_new_async (SysprofCaptureReader *reader, - SysprofSelection *selection, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +sysprof_marks_model_new_async (SysprofCaptureReader *reader, + SysprofMarksModelKind kind, + SysprofSelection *selection, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { - const SysprofCaptureFrameType types[] = { SYSPROF_CAPTURE_FRAME_MARK }; + static const SysprofCaptureFrameType ctrset[] = { SYSPROF_CAPTURE_FRAME_CTRDEF }; g_autoptr(SysprofCaptureCursor) cursor = NULL; g_autoptr(GTask) task = NULL; SysprofCaptureCondition *c; @@ -367,7 +457,36 @@ sysprof_marks_model_new_async (SysprofCaptureReader *reader, cursor = sysprof_capture_cursor_new (reader); - c = sysprof_capture_condition_new_where_type_in (G_N_ELEMENTS (types), types); + if (kind == SYSPROF_MARKS_MODEL_BOTH) + { + static const SysprofCaptureFrameType types[] = { + SYSPROF_CAPTURE_FRAME_CTRSET, + SYSPROF_CAPTURE_FRAME_MARK, + }; + + c = sysprof_capture_condition_new_where_type_in (G_N_ELEMENTS (types), types); + } + else if (kind == SYSPROF_MARKS_MODEL_MARKS) + { + static const SysprofCaptureFrameType types[] = { SYSPROF_CAPTURE_FRAME_MARK }; + + c = sysprof_capture_condition_new_where_type_in (G_N_ELEMENTS (types), types); + } + else if (kind == SYSPROF_MARKS_MODEL_COUNTERS) + { + static const SysprofCaptureFrameType types[] = { SYSPROF_CAPTURE_FRAME_CTRSET }; + + c = sysprof_capture_condition_new_where_type_in (G_N_ELEMENTS (types), types); + } + else + { + g_task_report_new_error (NULL, callback, user_data, + sysprof_marks_model_new_async, + G_IO_ERROR, + G_IO_ERROR_INVAL, + "Invalid arguments"); + return; + } if (selection) { @@ -377,7 +496,14 @@ sysprof_marks_model_new_async (SysprofCaptureReader *reader, sysprof_marks_model_selection_foreach_cb, &condition); if (condition) - c = sysprof_capture_condition_new_and (c, condition); + c = sysprof_capture_condition_new_and (c, g_steal_pointer (&condition)); + } + + if (kind & SYSPROF_MARKS_MODEL_COUNTERS) + { + c = sysprof_capture_condition_new_or ( + sysprof_capture_condition_new_where_type_in (G_N_ELEMENTS (ctrset), ctrset), + g_steal_pointer (&c)); } sysprof_capture_cursor_add_condition (cursor, g_steal_pointer (&c)); @@ -417,3 +543,23 @@ sysprof_marks_model_get_range (SysprofMarksModel *self, if (end_time != NULL) *end_time = self->max_end_time; } + +GType +sysprof_marks_model_kind_get_type (void) +{ + static GType type_id; + + if (g_once_init_enter (&type_id)) + { + static const GEnumValue values[] = { + { SYSPROF_MARKS_MODEL_MARKS, "SYSPROF_MARKS_MODEL_MARKS", "marks" }, + { SYSPROF_MARKS_MODEL_COUNTERS, "SYSPROF_MARKS_MODEL_COUNTERS", "counters" }, + { SYSPROF_MARKS_MODEL_BOTH, "SYSPROF_MARKS_MODEL_BOTH", "both" }, + { 0 }, + }; + GType _type_id = g_enum_register_static ("SysprofMarksModelKind", values); + g_once_init_leave (&type_id, _type_id); + } + + return type_id; +} diff --git a/src/libsysprof-ui/sysprof-marks-model.h b/src/libsysprof-ui/sysprof-marks-model.h index 54d833cb..203ad8ec 100644 --- a/src/libsysprof-ui/sysprof-marks-model.h +++ b/src/libsysprof-ui/sysprof-marks-model.h @@ -25,7 +25,8 @@ G_BEGIN_DECLS -#define SYSPROF_TYPE_MARKS_MODEL (sysprof_marks_model_get_type()) +#define SYSPROF_TYPE_MARKS_MODEL (sysprof_marks_model_get_type()) +#define SYSPROF_TYPE_MARKS_MODEL_KIND (sysprof_marks_model_kind_get_type()) typedef enum { @@ -34,21 +35,31 @@ typedef enum SYSPROF_MARKS_MODEL_COLUMN_BEGIN_TIME, SYSPROF_MARKS_MODEL_COLUMN_END_TIME, SYSPROF_MARKS_MODEL_COLUMN_DURATION, + SYSPROF_MARKS_MODEL_COLUMN_TEXT, } SysprofMarksModelColumn; -#define SYSPROF_MARKS_MODEL_COLUMN_LAST (SYSPROF_MARKS_MODEL_COLUMN_DURATION+1) +typedef enum +{ + SYSPROF_MARKS_MODEL_MARKS = 1, + SYSPROF_MARKS_MODEL_COUNTERS, + SYSPROF_MARKS_MODEL_BOTH = SYSPROF_MARKS_MODEL_MARKS | SYSPROF_MARKS_MODEL_COUNTERS, +} SysprofMarksModelKind; + +#define SYSPROF_MARKS_MODEL_COLUMN_LAST (SYSPROF_MARKS_MODEL_COLUMN_TEXT+1) G_DECLARE_FINAL_TYPE (SysprofMarksModel, sysprof_marks_model, SYSPROF, MARKS_MODEL, GObject) -void sysprof_marks_model_new_async (SysprofCaptureReader *reader, - SysprofSelection *selection, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -SysprofMarksModel *sysprof_marks_model_new_finish (GAsyncResult *result, - GError **error); -void sysprof_marks_model_get_range (SysprofMarksModel *self, - gint64 *begin_time, - gint64 *end_time); +GType sysprof_marks_model_kind_get_type (void) G_GNUC_CONST; +void sysprof_marks_model_new_async (SysprofCaptureReader *reader, + SysprofMarksModelKind kind, + SysprofSelection *selection, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +SysprofMarksModel *sysprof_marks_model_new_finish (GAsyncResult *result, + GError **error); +void sysprof_marks_model_get_range (SysprofMarksModel *self, + gint64 *begin_time, + gint64 *end_time); G_END_DECLS diff --git a/src/libsysprof-ui/sysprof-marks-view.c b/src/libsysprof-ui/sysprof-marks-view.c index f5312c02..54248f89 100644 --- a/src/libsysprof-ui/sysprof-marks-view.c +++ b/src/libsysprof-ui/sysprof-marks-view.c @@ -29,6 +29,8 @@ typedef struct { + SysprofMarksModelKind kind; + SysprofZoomManager *zoom_manager; gint64 capture_begin_time; @@ -44,6 +46,7 @@ typedef struct enum { PROP_0, + PROP_KIND, PROP_ZOOM_MANAGER, N_PROPS }; @@ -188,6 +191,10 @@ sysprof_marks_view_get_property (GObject *object, switch (prop_id) { + case PROP_KIND: + g_value_set_enum (value, priv->kind); + break; + case PROP_ZOOM_MANAGER: g_value_set_object (value, priv->zoom_manager); break; @@ -208,6 +215,10 @@ sysprof_marks_view_set_property (GObject *object, switch (prop_id) { + case PROP_KIND: + priv->kind = g_value_get_enum (value); + break; + case PROP_ZOOM_MANAGER: if (g_set_object (&priv->zoom_manager, g_value_get_object (value))) { @@ -245,6 +256,12 @@ sysprof_marks_view_class_init (SysprofMarksViewClass *klass) gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksView, duration_column); gtk_widget_class_bind_template_child_private (widget_class, SysprofMarksView, stack); + properties [PROP_KIND] = + g_param_spec_enum ("kind", NULL, NULL, + SYSPROF_TYPE_MARKS_MODEL_KIND, + SYSPROF_MARKS_MODEL_MARKS, + (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + properties [PROP_ZOOM_MANAGER] = g_param_spec_object ("zoom-manager", NULL, NULL, SYSPROF_TYPE_ZOOM_MANAGER, @@ -260,6 +277,8 @@ sysprof_marks_view_init (SysprofMarksView *self) { SysprofMarksViewPrivate *priv = sysprof_marks_view_get_instance_private (self); + priv->kind = SYSPROF_MARKS_MODEL_MARKS; + gtk_widget_init_template (GTK_WIDGET (self)); gtk_tree_selection_set_mode (gtk_tree_view_get_selection (priv->tree_view), @@ -338,6 +357,7 @@ sysprof_marks_view_load_async (SysprofMarksView *self, GAsyncReadyCallback callback, gpointer user_data) { + SysprofMarksViewPrivate *priv = sysprof_marks_view_get_instance_private (self); g_autoptr(GTask) task = NULL; g_return_if_fail (SYSPROF_IS_MARKS_VIEW (self)); @@ -352,6 +372,7 @@ sysprof_marks_view_load_async (SysprofMarksView *self, (GDestroyNotify) sysprof_capture_reader_unref); sysprof_marks_model_new_async (reader, + priv->kind, selection, cancellable, sysprof_marks_view_load_cb, diff --git a/src/libsysprof-ui/ui/sysprof-marks-view.ui b/src/libsysprof-ui/ui/sysprof-marks-view.ui index 06fafcbf..3baa8075 100644 --- a/src/libsysprof-ui/ui/sysprof-marks-view.ui +++ b/src/libsysprof-ui/ui/sysprof-marks-view.ui @@ -70,7 +70,7 @@ 1 - 1 + 5 2 3