From d510dd50da3650281c204aa0cb2234f7aa815c13 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Mon, 22 May 2023 16:46:36 -0700 Subject: [PATCH] libsysprof-analyze: add support for getting counter values --- src/libsysprof-analyze/meson.build | 2 + src/libsysprof-analyze/sysprof-analyze.h | 1 + .../sysprof-document-counter-value-private.h | 30 +++++ .../sysprof-document-counter-value.c | 124 ++++++++++++++++++ .../sysprof-document-counter-value.h | 45 +++++++ .../sysprof-document-counter.c | 98 +++++++++++++- .../sysprof-document-counter.h | 25 +++- .../sysprof-document-private.h | 4 +- src/libsysprof-analyze/sysprof-document.c | 4 +- .../tests/test-list-counters.c | 41 ++++++ 10 files changed, 364 insertions(+), 10 deletions(-) create mode 100644 src/libsysprof-analyze/sysprof-document-counter-value-private.h create mode 100644 src/libsysprof-analyze/sysprof-document-counter-value.c create mode 100644 src/libsysprof-analyze/sysprof-document-counter-value.h diff --git a/src/libsysprof-analyze/meson.build b/src/libsysprof-analyze/meson.build index 82028017..00e3f408 100644 --- a/src/libsysprof-analyze/meson.build +++ b/src/libsysprof-analyze/meson.build @@ -3,6 +3,7 @@ libsysprof_analyze_public_sources = [ 'sysprof-document.c', 'sysprof-document-allocation.c', 'sysprof-document-counter.c', + 'sysprof-document-counter-value.c', 'sysprof-document-ctrdef.c', 'sysprof-document-ctrset.c', 'sysprof-document-exit.c', @@ -52,6 +53,7 @@ libsysprof_analyze_public_headers = [ 'sysprof-document.h', 'sysprof-document-allocation.h', 'sysprof-document-counter.h', + 'sysprof-document-counter-value.h', 'sysprof-document-ctrdef.h', 'sysprof-document-ctrset.h', 'sysprof-document-exit.h', diff --git a/src/libsysprof-analyze/sysprof-analyze.h b/src/libsysprof-analyze/sysprof-analyze.h index 80c88fa7..2962fc67 100644 --- a/src/libsysprof-analyze/sysprof-analyze.h +++ b/src/libsysprof-analyze/sysprof-analyze.h @@ -29,6 +29,7 @@ G_BEGIN_DECLS # include "sysprof-document.h" # include "sysprof-document-allocation.h" # include "sysprof-document-counter.h" +# include "sysprof-document-counter-value.h" # include "sysprof-document-ctrdef.h" # include "sysprof-document-ctrset.h" # include "sysprof-document-exit.h" diff --git a/src/libsysprof-analyze/sysprof-document-counter-value-private.h b/src/libsysprof-analyze/sysprof-document-counter-value-private.h new file mode 100644 index 00000000..bc7319ae --- /dev/null +++ b/src/libsysprof-analyze/sysprof-document-counter-value-private.h @@ -0,0 +1,30 @@ +/* sysprof-document-counter-value-private.h + * + * Copyright 2023 Christian Hergert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#pragma once + +#include "sysprof-document-counter-value.h" +#include "sysprof-document-private.h" + +G_BEGIN_DECLS + +SysprofDocumentCounterValue *_sysprof_document_counter_value_new (const SysprofDocumentTimedValue *value); + +G_END_DECLS diff --git a/src/libsysprof-analyze/sysprof-document-counter-value.c b/src/libsysprof-analyze/sysprof-document-counter-value.c new file mode 100644 index 00000000..8be6e53c --- /dev/null +++ b/src/libsysprof-analyze/sysprof-document-counter-value.c @@ -0,0 +1,124 @@ +/* sysprof-document-counter-value.c + * + * Copyright 2023 Christian Hergert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include "config.h" + +#include "sysprof-document-counter-value-private.h" + +struct _SysprofDocumentCounterValue +{ + GObject parent_instance; + SysprofDocumentTimedValue value; +}; + +enum { + PROP_0, + PROP_TIME, + N_PROPS +}; + +G_DEFINE_FINAL_TYPE (SysprofDocumentCounterValue, sysprof_document_counter_value, G_TYPE_OBJECT) + +static GParamSpec *properties [N_PROPS]; + +static void +sysprof_document_counter_value_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SysprofDocumentCounterValue *self = SYSPROF_DOCUMENT_COUNTER_VALUE (object); + + switch (prop_id) + { + case PROP_TIME: + g_value_set_int64 (value, sysprof_document_counter_value_get_time (self)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +sysprof_document_counter_value_class_init (SysprofDocumentCounterValueClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = sysprof_document_counter_value_get_property; + + properties [PROP_TIME] = + g_param_spec_int64 ("time", NULL, NULL, + G_MININT64, 0, G_MAXINT64, + (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_properties (object_class, N_PROPS, properties); +} + +static void +sysprof_document_counter_value_init (SysprofDocumentCounterValue *self) +{ +} + +SysprofDocumentCounterValue * +_sysprof_document_counter_value_new (const SysprofDocumentTimedValue *value) +{ + SysprofDocumentCounterValue *self; + + self = g_object_new (SYSPROF_TYPE_DOCUMENT_COUNTER_VALUE, NULL); + self->value = *value; + + return self; +} + +gint64 +sysprof_document_counter_value_get_time (SysprofDocumentCounterValue *self) +{ + g_return_val_if_fail (SYSPROF_IS_DOCUMENT_COUNTER_VALUE (self), 0); + + return self->value.time; +} + +void +sysprof_document_counter_value_get_value (SysprofDocumentCounterValue *self, + GValue *value) +{ + g_return_if_fail (SYSPROF_IS_DOCUMENT_COUNTER_VALUE (self)); + g_return_if_fail (G_IS_VALUE (value)); + + if (G_VALUE_HOLDS_INT64 (value)) + g_value_set_int64 (value, self->value.v_int64); + else if (G_VALUE_HOLDS_DOUBLE (value)) + g_value_set_double (value, self->value.v_double); + else + g_warning_once ("Unsupported value type %s", G_VALUE_TYPE_NAME (value)); +} + +gint64 +sysprof_document_counter_value_get_value_int64 (SysprofDocumentCounterValue *self) +{ + return self->value.v_int64; +} + +double +sysprof_document_counter_value_get_value_double (SysprofDocumentCounterValue *self) +{ + return self->value.v_double; +} diff --git a/src/libsysprof-analyze/sysprof-document-counter-value.h b/src/libsysprof-analyze/sysprof-document-counter-value.h new file mode 100644 index 00000000..d780baf8 --- /dev/null +++ b/src/libsysprof-analyze/sysprof-document-counter-value.h @@ -0,0 +1,45 @@ +/* sysprof-document-counter-value.h + * + * Copyright 2023 Christian Hergert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#pragma once + +#include + +#include + +G_BEGIN_DECLS + +#define SYSPROF_TYPE_DOCUMENT_COUNTER_VALUE (sysprof_document_counter_value_get_type()) + +SYSPROF_AVAILABLE_IN_ALL +G_DECLARE_FINAL_TYPE (SysprofDocumentCounterValue, sysprof_document_counter_value, SYSPROF, DOCUMENT_COUNTER_VALUE, GObject) + +SYSPROF_AVAILABLE_IN_ALL +gint64 sysprof_document_counter_value_get_time (SysprofDocumentCounterValue *self); +SYSPROF_AVAILABLE_IN_ALL +void sysprof_document_counter_value_get_value (SysprofDocumentCounterValue *self, + GValue *value); +SYSPROF_AVAILABLE_IN_ALL +gint64 sysprof_document_counter_value_get_value_int64 (SysprofDocumentCounterValue *self); +SYSPROF_AVAILABLE_IN_ALL +double sysprof_document_counter_value_get_value_double (SysprofDocumentCounterValue *self); + + +G_END_DECLS diff --git a/src/libsysprof-analyze/sysprof-document-counter.c b/src/libsysprof-analyze/sysprof-document-counter.c index 7cdb838b..e6b31a5a 100644 --- a/src/libsysprof-analyze/sysprof-document-counter.c +++ b/src/libsysprof-analyze/sysprof-document-counter.c @@ -21,6 +21,8 @@ #include "config.h" #include "sysprof-document-counter.h" +#include "sysprof-document-counter-value-private.h" +#include "sysprof-document-private.h" struct _SysprofDocumentCounter { @@ -42,7 +44,43 @@ enum { N_PROPS }; -G_DEFINE_FINAL_TYPE (SysprofDocumentCounter, sysprof_document_counter, G_TYPE_OBJECT) +static guint +sysprof_document_counter_get_n_items (GListModel *model) +{ + return sysprof_document_counter_get_n_values (SYSPROF_DOCUMENT_COUNTER (model)); +} + +static GType +sysprof_document_counter_get_item_type (GListModel *model) +{ + return SYSPROF_TYPE_DOCUMENT_COUNTER_VALUE; +} + +static gpointer +sysprof_document_counter_get_item (GListModel *model, + guint position) +{ + SysprofDocumentCounter *self = SYSPROF_DOCUMENT_COUNTER (model); + const SysprofDocumentTimedValue *value; + + if (position >= self->values->len) + return NULL; + + value = &g_array_index (self->values, SysprofDocumentTimedValue, position); + + return _sysprof_document_counter_value_new (value); +} + +static void +list_model_iface_init (GListModelInterface *iface) +{ + iface->get_n_items = sysprof_document_counter_get_n_items; + iface->get_item_type = sysprof_document_counter_get_item_type; + iface->get_item = sysprof_document_counter_get_item; +} + +G_DEFINE_FINAL_TYPE_WITH_CODE (SysprofDocumentCounter, sysprof_document_counter, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init)) static GParamSpec *properties [N_PROPS]; @@ -192,3 +230,61 @@ sysprof_document_counter_get_value_type (SysprofDocumentCounter *self) return G_TYPE_INVALID; } + +guint +sysprof_document_counter_get_n_values (SysprofDocumentCounter *self) +{ + g_return_val_if_fail (SYSPROF_IS_DOCUMENT_COUNTER (self), 0); + + return self->values->len; +} + +void +sysprof_document_counter_get_value (SysprofDocumentCounter *self, + guint nth, + gint64 *time, + GValue *value) +{ + g_return_if_fail (SYSPROF_IS_DOCUMENT_COUNTER (self)); + g_return_if_fail (nth < self->values->len); + g_return_if_fail (value == NULL || G_IS_VALUE (value)); + + if (time != NULL) + *time = g_array_index (self->values, SysprofDocumentTimedValue, nth).time; + + if (value == NULL) + return; + + if (G_VALUE_HOLDS_INT64 (value)) + g_value_set_int64 (value, g_array_index (self->values, SysprofDocumentTimedValue, nth).v_int64); + else if (G_VALUE_HOLDS_DOUBLE (value)) + g_value_set_double (value, g_array_index (self->values, SysprofDocumentTimedValue, nth).v_double); +} + +gint64 +sysprof_document_counter_get_value_int64 (SysprofDocumentCounter *self, + guint nth, + gint64 *time) +{ + g_return_val_if_fail (SYSPROF_IS_DOCUMENT_COUNTER (self), 0); + g_return_val_if_fail (nth < self->values->len, 0); + + if (time != NULL) + *time = g_array_index (self->values, SysprofDocumentTimedValue, nth).time; + + return g_array_index (self->values, SysprofDocumentTimedValue, nth).v_int64; +} + +double +sysprof_document_counter_get_value_double (SysprofDocumentCounter *self, + guint nth, + gint64 *time) +{ + g_return_val_if_fail (SYSPROF_IS_DOCUMENT_COUNTER (self), 0); + g_return_val_if_fail (nth < self->values->len, 0); + + if (time != NULL) + *time = g_array_index (self->values, SysprofDocumentTimedValue, nth).time; + + return g_array_index (self->values, SysprofDocumentTimedValue, nth).v_double; +} diff --git a/src/libsysprof-analyze/sysprof-document-counter.h b/src/libsysprof-analyze/sysprof-document-counter.h index af3e1f7e..cf796e38 100644 --- a/src/libsysprof-analyze/sysprof-document-counter.h +++ b/src/libsysprof-analyze/sysprof-document-counter.h @@ -32,14 +32,29 @@ SYSPROF_AVAILABLE_IN_ALL G_DECLARE_FINAL_TYPE (SysprofDocumentCounter, sysprof_document_counter, SYSPROF, DOCUMENT_COUNTER, GObject) SYSPROF_AVAILABLE_IN_ALL -const char *sysprof_document_counter_get_category (SysprofDocumentCounter *self); +const char *sysprof_document_counter_get_category (SysprofDocumentCounter *self); SYSPROF_AVAILABLE_IN_ALL -const char *sysprof_document_counter_get_description (SysprofDocumentCounter *self); +const char *sysprof_document_counter_get_description (SysprofDocumentCounter *self); SYSPROF_AVAILABLE_IN_ALL -const char *sysprof_document_counter_get_name (SysprofDocumentCounter *self); +const char *sysprof_document_counter_get_name (SysprofDocumentCounter *self); SYSPROF_AVAILABLE_IN_ALL -guint sysprof_document_counter_get_id (SysprofDocumentCounter *self); +guint sysprof_document_counter_get_id (SysprofDocumentCounter *self); SYSPROF_AVAILABLE_IN_ALL -GType sysprof_document_counter_get_value_type (SysprofDocumentCounter *self); +GType sysprof_document_counter_get_value_type (SysprofDocumentCounter *self); +SYSPROF_AVAILABLE_IN_ALL +guint sysprof_document_counter_get_n_values (SysprofDocumentCounter *self); +SYSPROF_AVAILABLE_IN_ALL +void sysprof_document_counter_get_value (SysprofDocumentCounter *self, + guint nth, + gint64 *time, + GValue *value); +SYSPROF_AVAILABLE_IN_ALL +gint64 sysprof_document_counter_get_value_int64 (SysprofDocumentCounter *self, + guint nth, + gint64 *time); +SYSPROF_AVAILABLE_IN_ALL +double sysprof_document_counter_get_value_double (SysprofDocumentCounter *self, + guint nth, + gint64 *time); G_END_DECLS diff --git a/src/libsysprof-analyze/sysprof-document-private.h b/src/libsysprof-analyze/sysprof-document-private.h index 5dec04ef..5f93ba07 100644 --- a/src/libsysprof-analyze/sysprof-document-private.h +++ b/src/libsysprof-analyze/sysprof-document-private.h @@ -27,7 +27,7 @@ G_BEGIN_DECLS -typedef struct _SysprofDocumentCounterValue +typedef struct _SysprofDocumentTimedValue { gint64 time; union { @@ -35,7 +35,7 @@ typedef struct _SysprofDocumentCounterValue double v_double; guint8 v_raw[8]; }; -} SysprofDocumentCounterValue; +} SysprofDocumentTimedValue; void _sysprof_document_new_async (GMappedFile *mapped_file, GCancellable *cancellable, diff --git a/src/libsysprof-analyze/sysprof-document.c b/src/libsysprof-analyze/sysprof-document.c index 93bf6769..665069dd 100644 --- a/src/libsysprof-analyze/sysprof-document.c +++ b/src/libsysprof-analyze/sysprof-document.c @@ -479,7 +479,7 @@ sysprof_document_load_counters (SysprofDocument *self) for (guint j = 0; j < n_counters; j++) { - g_autoptr(GArray) values = g_array_new (FALSE, FALSE, sizeof (SysprofDocumentCounterValue)); + g_autoptr(GArray) values = g_array_new (FALSE, FALSE, sizeof (SysprofDocumentTimedValue)); const char *category; const char *name; const char *description; @@ -520,7 +520,7 @@ sysprof_document_load_counters (SysprofDocument *self) { g_autoptr(SysprofDocumentCtrset) ctrset = g_list_model_get_item (model, i); guint n_values = sysprof_document_ctrset_get_n_values (ctrset); - SysprofDocumentCounterValue ctrval; + SysprofDocumentTimedValue ctrval; ctrval.time = sysprof_document_frame_get_time (SYSPROF_DOCUMENT_FRAME (ctrset)); diff --git a/src/libsysprof-analyze/tests/test-list-counters.c b/src/libsysprof-analyze/tests/test-list-counters.c index fa54b1ae..e5061a7f 100644 --- a/src/libsysprof-analyze/tests/test-list-counters.c +++ b/src/libsysprof-analyze/tests/test-list-counters.c @@ -22,16 +22,31 @@ #include "sysprof-document-private.h" +static gboolean show_values; +static const GOptionEntry entries[] = { + { "values", 'v', 0, G_OPTION_ARG_NONE, &show_values, "Show values along with counter information" }, + { 0 } +}; + int main (int argc, char *argv[]) { + g_autoptr(GOptionContext) context = g_option_context_new ("- list counter information from capture"); g_autoptr(SysprofDocumentLoader) loader = NULL; g_autoptr(SysprofDocument) document = NULL; g_autoptr(GListModel) model = NULL; g_autoptr(GError) error = NULL; guint n_items; + g_option_context_add_main_entries (context, entries, NULL); + + if (!g_option_context_parse (context, &argc, &argv, &error)) + { + g_printerr ("%s\n", error->message); + return 1; + } + if (argc < 2) { g_printerr ("usage: %s CAPTURE_FILE\n", argv[0]); @@ -60,6 +75,32 @@ main (int argc, sysprof_document_counter_get_category (counter), sysprof_document_counter_get_name (counter), sysprof_document_counter_get_description (counter)); + + if (show_values) + { + guint n_values = sysprof_document_counter_get_n_values (counter); + + if (sysprof_document_counter_get_value_type (counter) == G_TYPE_INT64) + { + for (guint j = 0; j < n_values; j++) + { + gint64 t; + gint64 v = sysprof_document_counter_get_value_int64 (counter, j, &t); + + g_print (" %03u: %"G_GINT64_FORMAT": %"G_GINT64_FORMAT"\n", j, t, v); + } + } + else if (sysprof_document_counter_get_value_type (counter) == G_TYPE_DOUBLE) + { + for (guint j = 0; j < n_values; j++) + { + gint64 t; + double v = sysprof_document_counter_get_value_int64 (counter, j, &t); + + g_print (" %03u: %"G_GINT64_FORMAT": %lf\n", j, t, v); + } + } + } } return 0;