[sysprof] visualizer: Make proper rectangles from i915 GPU events.
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [sysprof] visualizer: Make proper rectangles from i915 GPU events.
- Date: Thu, 17 May 2018 18:42:25 +0000 (UTC)
commit 94bb2fba0dc472d64803cce57bcc93349fa91d86
Author: Eric Anholt <eric anholt net>
Date: Thu May 17 14:46:50 2018 +0100
visualizer: Make proper rectangles from i915 GPU events.
This reveals that we've got really bogus times from these events. I
think there are two things here: the begin is the submit time, not the
submit-to-hardware time. And the end time is retire, which is too
delayed to be really useful. We need to move i915 over to the
low-level tracepoints.
However, this code proved to be useful for vc4, where I have good
timings.
lib/visualizers/sp-mark-visualizer-row.c | 125 ++++++++++++++++++++++++++++-
1 files changed, 120 insertions(+), 5 deletions(-)
---
diff --git a/lib/visualizers/sp-mark-visualizer-row.c b/lib/visualizers/sp-mark-visualizer-row.c
index 16e0581..7d0e922 100644
--- a/lib/visualizers/sp-mark-visualizer-row.c
+++ b/lib/visualizers/sp-mark-visualizer-row.c
@@ -54,8 +54,15 @@ typedef struct
gchar *group;
SpCaptureCursor *cursor;
Rectangles *rects;
+ GHashTable *inferred_rects;
} BuildState;
+typedef struct {
+ gint64 time;
+ gchar *name;
+ gchar *message;
+} InferredRect;
+
enum {
PROP_0,
PROP_GROUP,
@@ -68,13 +75,97 @@ G_DEFINE_TYPE_WITH_PRIVATE (SpMarkVisualizerRow, sp_mark_visualizer_row, SP_TYPE
static GParamSpec *properties [N_PROPS];
static void
+free_inferred_rect (InferredRect *rect)
+{
+ g_free (rect->name);
+ g_free (rect->message);
+ g_free (rect);
+}
+
+static void
+add_inferred_rect_point (BuildState *state,
+ InferredRect *rect)
+{
+ rectangles_add (state->rects,
+ rect->time,
+ rect->time,
+ rect->name,
+ rect->message);
+}
+
+static void
build_state_free (BuildState *state)
{
+ g_hash_table_remove_all (state->inferred_rects);
+ g_clear_pointer (&state->inferred_rects, g_hash_table_unref);
g_free (state->group);
g_object_unref (state->cursor);
g_slice_free (BuildState, state);
}
+/* Creates rectangles for GPU marks.
+ *
+ * GPU marks come in as a begin and an end, but since those things are
+ * processessed on potentially different CPUs, perf doesn't record
+ * them in sequence order in the mmap ringbuffer. Thus, we have to
+ * shuffle things back around at visualization time.
+ */
+static gboolean
+process_gpu_mark (BuildState *state,
+ const SpCaptureMark *mark)
+{
+ InferredRect *rect = g_hash_table_lookup (state->inferred_rects,
+ mark->message);
+
+ if (rect)
+ {
+ gboolean ours_begins = strstr (mark->name, "begin") != NULL;
+ gboolean theirs_begins = strstr (rect->name, "begin") != NULL;
+
+ if (ours_begins != theirs_begins)
+ {
+ rectangles_add (state->rects,
+ ours_begins ? mark->frame.time : rect->time,
+ ours_begins ? rect->time : mark->frame.time,
+ ours_begins ? mark->name : rect->name,
+ rect->message);
+ }
+ else
+ {
+ /* Something went weird with the tracking (GPU hang caused
+ * two starts?), so just put up both time points as vertical
+ * bars for now.
+ */
+ rectangles_add (state->rects,
+ mark->frame.time,
+ mark->frame.time,
+ mark->name,
+ mark->message);
+
+ add_inferred_rect_point (state, rect);
+ }
+
+ g_hash_table_remove (state->inferred_rects,
+ rect->message);
+ }
+ else
+ {
+ rect = g_malloc0 (sizeof (*rect));
+ if (!rect)
+ return FALSE;
+
+ rect->name = g_strdup (mark->name);
+ rect->message = g_strdup (mark->message);
+ rect->time = mark->frame.time;
+ g_hash_table_insert (state->inferred_rects,
+ rect->message,
+ rect);
+ }
+
+ return TRUE;
+}
+
+
static gboolean
sp_mark_visualizer_row_add_rect (const SpCaptureFrame *frame,
gpointer user_data)
@@ -88,11 +179,17 @@ sp_mark_visualizer_row_add_rect (const SpCaptureFrame *frame,
g_assert (state->rects != NULL);
if (g_strcmp0 (mark->group, state->group) == 0)
- rectangles_add (state->rects,
- frame->time,
- frame->time + mark->duration,
- mark->name,
- mark->message);
+ {
+ if (strstr (mark->name, "gpu begin") != NULL ||
+ strstr (mark->name, "gpu end") != NULL)
+ process_gpu_mark (state, mark);
+ else
+ rectangles_add (state->rects,
+ frame->time,
+ frame->time + mark->duration,
+ mark->name,
+ mark->message);
+ }
return TRUE;
}
@@ -104,6 +201,8 @@ sp_mark_visualizer_row_worker (GTask *task,
GCancellable *cancellable)
{
BuildState *state = task_data;
+ GHashTableIter iter;
+ gpointer key, value;
gint64 end_time;
g_assert (G_IS_TASK (task));
@@ -112,6 +211,19 @@ sp_mark_visualizer_row_worker (GTask *task,
g_assert (SP_IS_CAPTURE_CURSOR (state->cursor));
sp_capture_cursor_foreach (state->cursor, sp_mark_visualizer_row_add_rect, state);
+
+ /* If any inferred rects are left incomplete, just drop them in as
+ * point events for now.
+ */
+ g_hash_table_iter_init (&iter, state->inferred_rects);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ InferredRect *rect = value;
+
+ add_inferred_rect_point (state, rect);
+ }
+ g_hash_table_remove_all (state->inferred_rects);
+
end_time = sp_capture_reader_get_end_time (sp_capture_cursor_get_reader (state->cursor));
rectangles_set_end_time (state->rects, end_time);
g_task_return_pointer (task, g_steal_pointer (&state->rects), (GDestroyNotify)rectangles_free);
@@ -200,6 +312,9 @@ sp_mark_visualizer_row_reload (SpMarkVisualizerRow *self)
sp_capture_cursor_add_condition (cursor, g_steal_pointer (&condition));
state = g_slice_new0 (BuildState);
+ state->inferred_rects = g_hash_table_new_full (g_str_hash, g_str_equal,
+ NULL,
+ (GDestroyNotify)free_inferred_rect);
state->group = g_strdup (priv->group);
state->cursor = g_steal_pointer (&cursor);
state->rects = rectangles_new (sp_capture_reader_get_start_time (priv->reader),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]