From 126002c5c9519eadee868b923f88213ca21eb307 Mon Sep 17 00:00:00 2001 From: Ell Date: Thu, 30 Jul 2020 00:32:30 +0300 Subject: [PATCH] app: allow controlling performance-log parameters through the UI When recording a performance log, allow setting the log parametrs through the file dialog. Currently, this includes the sample frequency, and the option to include backtraces. These options are still controllable through the GIMP_PERFORMANCE_LOG_SAMPLE_FREQUENCY and GIMP_PERFORMANCE_LOG_BACKTRACE environment variables. When set, the variables override the values entered through the UI. --- app/actions/dashboard-commands.c | 130 ++++++++++++++++++++++++++----- app/widgets/gimpdashboard.c | 93 ++++++++++++++-------- app/widgets/gimpdashboard.h | 9 +++ app/widgets/widgets-types.h | 2 + 4 files changed, 183 insertions(+), 51 deletions(-) diff --git a/app/actions/dashboard-commands.c b/app/actions/dashboard-commands.c index e54c242f49..8906489a0e 100644 --- a/app/actions/dashboard-commands.c +++ b/app/actions/dashboard-commands.c @@ -37,15 +37,25 @@ #include "gimp-intl.h" +typedef struct +{ + GFile *folder; + GimpDashboardLogParams params; +} DashboardLogDialogInfo; + + /* local function prototypes */ -static void dashboard_log_record_response (GtkWidget *dialog, - int response_id, - GimpDashboard *dashboard); +static void dashboard_log_record_response (GtkWidget *dialog, + int response_id, + GimpDashboard *dashboard); -static void dashboard_log_add_marker_response (GtkWidget *dialog, - const gchar *description, - GimpDashboard *dashboard); +static void dashboard_log_add_marker_response (GtkWidget *dialog, + const gchar *description, + GimpDashboard *dashboard); + +static DashboardLogDialogInfo * dashboard_log_dialog_info_new (GimpDashboard *dashboard); +static void dashboard_log_dialog_info_free (DashboardLogDialogInfo *info); /* public functions */ @@ -94,8 +104,13 @@ dashboard_log_record_cmd_callback (GimpAction *action, if (! dialog) { - GtkFileFilter *filter; - GFile *folder; + GtkFileFilter *filter; + DashboardLogDialogInfo *info; + GtkWidget *hbox; + GtkWidget *hbox2; + GtkWidget *label; + GtkWidget *spinbutton; + GtkWidget *toggle; dialog = gtk_file_chooser_dialog_new ( "Record Performance Log", NULL, GTK_FILE_CHOOSER_ACTION_SAVE, @@ -134,18 +149,69 @@ dashboard_log_record_cmd_callback (GimpAction *action, gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dialog), filter); - folder = g_object_get_data (G_OBJECT (dashboard), - "gimp-dashboard-log-record-folder"); + info = g_object_get_data (G_OBJECT (dashboard), + "gimp-dashboard-log-dialog-info"); - if (folder) + if (! info) + { + info = dashboard_log_dialog_info_new (dashboard); + + g_object_set_data_full ( + G_OBJECT (dashboard), + "gimp-dashboard-log-dialog-info", info, + (GDestroyNotify) dashboard_log_dialog_info_free); + } + + if (info->folder) { gtk_file_chooser_set_current_folder_file ( - GTK_FILE_CHOOSER (dialog), folder, NULL); + GTK_FILE_CHOOSER (dialog), info->folder, NULL); } gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), "gimp-performance.log"); + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 16); + gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (dialog), hbox); + gtk_widget_show (hbox); + + hbox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8); + gimp_help_set_help_data (hbox2, _("Log samples per second"), NULL); + gtk_box_pack_start (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0); + gtk_widget_show (hbox2); + + label = gtk_label_new_with_mnemonic (_("Sample fre_quency:")); + gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + spinbutton = gimp_spin_button_new_with_range (1, 1000, 1); + gtk_box_pack_start (GTK_BOX (hbox2), spinbutton, FALSE, FALSE, 0); + gtk_widget_show (spinbutton); + + gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinbutton), + info->params.sample_frequency); + + g_signal_connect (gtk_spin_button_get_adjustment ( + GTK_SPIN_BUTTON (spinbutton)), + "value-changed", + G_CALLBACK (gimp_int_adjustment_update), + &info->params.sample_frequency); + + gtk_label_set_mnemonic_widget (GTK_LABEL (label), spinbutton); + + toggle = gtk_check_button_new_with_mnemonic (_("_Backtrace")); + gimp_help_set_help_data (toggle, _("Include backtraces in log"), + NULL); + gtk_box_pack_start (GTK_BOX (hbox), toggle, FALSE, FALSE, 0); + gtk_widget_show (toggle); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), + info->params.backtrace); + + g_signal_connect (toggle, "toggled", + G_CALLBACK (gimp_toggle_button_update), + &info->params.backtrace); + g_signal_connect (dialog, "response", G_CALLBACK (dashboard_log_record_response), dashboard); @@ -253,15 +319,22 @@ dashboard_log_record_response (GtkWidget *dialog, { if (response_id == GTK_RESPONSE_OK) { - GFile *file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog)); - GError *error = NULL; + GFile *file; + DashboardLogDialogInfo *info; + GError *error = NULL; - g_object_set_data_full (G_OBJECT (dashboard), - "gimp-dashboard-log-record-folder", - g_file_get_parent (file), - g_object_unref); + file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog)); - if (! gimp_dashboard_log_start_recording (dashboard, file, &error)) + info = g_object_get_data (G_OBJECT (dashboard), + "gimp-dashboard-log-dialog-info"); + + g_return_if_fail (info != NULL); + + g_set_object (&info->folder, g_file_get_parent (file)); + + if (! gimp_dashboard_log_start_recording (dashboard, + file, &info->params, + &error)) { gimp_message_literal ( gimp_editor_get_ui_manager (GIMP_EDITOR (dashboard))->gimp, @@ -283,3 +356,22 @@ dashboard_log_add_marker_response (GtkWidget *dialog, { gimp_dashboard_log_add_marker (dashboard, description); } + +static DashboardLogDialogInfo * +dashboard_log_dialog_info_new (GimpDashboard *dashboard) +{ + DashboardLogDialogInfo *info = g_slice_new (DashboardLogDialogInfo); + + info->folder = NULL; + info->params = *gimp_dashboard_log_get_default_params (dashboard); + + return info; +} + +static void +dashboard_log_dialog_info_free (DashboardLogDialogInfo *info) +{ + g_clear_object (&info->folder); + + g_slice_free (DashboardLogDialogInfo, info); +} diff --git a/app/widgets/gimpdashboard.c b/app/widgets/gimpdashboard.c index 2f3f13dc91..46305922f2 100644 --- a/app/widgets/gimpdashboard.c +++ b/app/widgets/gimpdashboard.c @@ -94,7 +94,10 @@ #define CPU_ACTIVE_OFF /* individual cpu usage is below */ 0.25 #define LOG_VERSION 1 -#define LOG_SAMPLE_FREQUENCY 10 /* samples per second */ +#define LOG_SAMPLE_FREQUENCY_MIN 1 /* samples per second */ +#define LOG_SAMPLE_FREQUENCY_MAX 1000 /* samples per second */ +#define LOG_DEFAULT_SAMPLE_FREQUENCY 10 /* samples per second */ +#define LOG_DEFAULT_BACKTRACE TRUE typedef enum @@ -311,12 +314,11 @@ struct _GimpDashboardPrivate GOutputStream *log_output; GError *log_error; + GimpDashboardLogParams log_params; gint64 log_start_time; - gint log_sample_frequency; gint log_n_samples; gint log_n_markers; VariableData log_variables[N_VARIABLES]; - gboolean log_include_backtrace; GimpBacktrace *log_backtrace; GHashTable *log_addresses; @@ -1757,9 +1759,14 @@ gimp_dashboard_sample (GimpDashboard *dashboard) update_interval = priv->update_interval * G_TIME_SPAN_SECOND / 1000; if (priv->log_output) - sample_interval = G_TIME_SPAN_SECOND / priv->log_sample_frequency; + { + sample_interval = G_TIME_SPAN_SECOND / + priv->log_params.sample_frequency; + } else - sample_interval = update_interval; + { + sample_interval = update_interval; + } end_time = last_sample_time + sample_interval; @@ -3650,7 +3657,7 @@ gimp_dashboard_log_sample (GimpDashboard *dashboard, "\n"); } - if (priv->log_include_backtrace) + if (priv->log_params.backtrace) backtrace = gimp_backtrace_new (FALSE); if (backtrace) @@ -4257,9 +4264,10 @@ gimp_dashboard_new (Gimp *gimp, } gboolean -gimp_dashboard_log_start_recording (GimpDashboard *dashboard, - GFile *file, - GError **error) +gimp_dashboard_log_start_recording (GimpDashboard *dashboard, + GFile *file, + const GimpDashboardLogParams *params, + GError **error) { GimpDashboardPrivate *priv; GimpUIManager *ui_manager; @@ -4281,6 +4289,27 @@ gimp_dashboard_log_start_recording (GimpDashboard *dashboard, g_return_val_if_fail (! gimp_dashboard_log_is_recording (dashboard), FALSE); + if (! params) + params = gimp_dashboard_log_get_default_params (dashboard); + + priv->log_params = *params; + + if (g_getenv ("GIMP_PERFORMANCE_LOG_SAMPLE_FREQUENCY")) + { + priv->log_params.sample_frequency = + atoi (g_getenv ("GIMP_PERFORMANCE_LOG_SAMPLE_FREQUENCY")); + } + + if (g_getenv ("GIMP_PERFORMANCE_LOG_BACKTRACE")) + { + priv->log_params.backtrace = + atoi (g_getenv ("GIMP_PERFORMANCE_LOG_BACKTRACE")) ? 1 : 0; + } + + priv->log_params.sample_frequency = CLAMP (priv->log_params.sample_frequency, + LOG_SAMPLE_FREQUENCY_MIN, + LOG_SAMPLE_FREQUENCY_MAX); + g_mutex_lock (&priv->mutex); priv->log_output = G_OUTPUT_STREAM (g_file_replace (file, @@ -4294,28 +4323,14 @@ gimp_dashboard_log_start_recording (GimpDashboard *dashboard, return FALSE; } - priv->log_error = NULL; - priv->log_start_time = g_get_monotonic_time (); - priv->log_sample_frequency = LOG_SAMPLE_FREQUENCY; - priv->log_n_samples = 0; - priv->log_n_markers = 0; - priv->log_include_backtrace = TRUE; - priv->log_backtrace = NULL; - priv->log_addresses = g_hash_table_new (NULL, NULL); + priv->log_error = NULL; + priv->log_start_time = g_get_monotonic_time (); + priv->log_n_samples = 0; + priv->log_n_markers = 0; + priv->log_backtrace = NULL; + priv->log_addresses = g_hash_table_new (NULL, NULL); - if (g_getenv ("GIMP_PERFORMANCE_LOG_SAMPLE_FREQUENCY")) - { - priv->log_sample_frequency = - atoi (g_getenv ("GIMP_PERFORMANCE_LOG_SAMPLE_FREQUENCY")); - - priv->log_sample_frequency = CLAMP (priv->log_sample_frequency, - 1, 1000); - } - - if (g_getenv ("GIMP_PERFORMANCE_LOG_NO_BACKTRACE")) - priv->log_include_backtrace = FALSE; - - if (priv->log_include_backtrace) + if (priv->log_params.backtrace) has_backtrace = gimp_backtrace_start (); else has_backtrace = FALSE; @@ -4331,7 +4346,7 @@ gimp_dashboard_log_start_recording (GimpDashboard *dashboard, "%d\n" "%d\n" "\n", - priv->log_sample_frequency, + priv->log_params.sample_frequency, has_backtrace); gimp_dashboard_log_printf (dashboard, @@ -4558,7 +4573,7 @@ gimp_dashboard_log_stop_recording (GimpDashboard *dashboard, "\n" "\n"); - if (priv->log_include_backtrace) + if (priv->log_params.backtrace) gimp_backtrace_stop (); if (! priv->log_error) @@ -4612,6 +4627,20 @@ gimp_dashboard_log_is_recording (GimpDashboard *dashboard) return priv->log_output != NULL; } +const GimpDashboardLogParams * +gimp_dashboard_log_get_default_params (GimpDashboard *dashboard) +{ + static const GimpDashboardLogParams default_params = + { + .sample_frequency = LOG_DEFAULT_SAMPLE_FREQUENCY, + .backtrace = LOG_DEFAULT_BACKTRACE, + }; + + g_return_val_if_fail (GIMP_IS_DASHBOARD (dashboard), NULL); + + return &default_params; +} + void gimp_dashboard_log_add_marker (GimpDashboard *dashboard, const gchar *description) diff --git a/app/widgets/gimpdashboard.h b/app/widgets/gimpdashboard.h index 3255775cd0..3a5b639aa4 100644 --- a/app/widgets/gimpdashboard.h +++ b/app/widgets/gimpdashboard.h @@ -25,6 +25,13 @@ #include "gimpeditor.h" +struct _GimpDashboardLogParams +{ + gint sample_frequency; + gboolean backtrace; +}; + + #define GIMP_TYPE_DASHBOARD (gimp_dashboard_get_type ()) #define GIMP_DASHBOARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_DASHBOARD, GimpDashboard)) #define GIMP_DASHBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_DASHBOARD, GimpDashboardClass)) @@ -56,10 +63,12 @@ GtkWidget * gimp_dashboard_new (Gimp gboolean gimp_dashboard_log_start_recording (GimpDashboard *dashboard, GFile *file, + const GimpDashboardLogParams *params, GError **error); gboolean gimp_dashboard_log_stop_recording (GimpDashboard *dashboard, GError **error); gboolean gimp_dashboard_log_is_recording (GimpDashboard *dashboard); +const GimpDashboardLogParams * gimp_dashboard_log_get_default_params (GimpDashboard *dashboard); void gimp_dashboard_log_add_marker (GimpDashboard *dashboard, const gchar *description); diff --git a/app/widgets/widgets-types.h b/app/widgets/widgets-types.h index 852e2fdf1d..e7272cc97f 100644 --- a/app/widgets/widgets-types.h +++ b/app/widgets/widgets-types.h @@ -292,6 +292,8 @@ typedef struct _GimpToggleActionEntry GimpToggleActionEntry; typedef struct _GimpDialogFactoryEntry GimpDialogFactoryEntry; +typedef struct _GimpDashboardLogParams GimpDashboardLogParams; + /* function types */