[gimp/gimp-2-10] app: add progressive performance logs



commit 60ca61109652ddb2df739560d8fbb59c6e3b222d
Author: Ell <ell_se yahoo com>
Date:   Thu Jul 30 00:41:00 2020 +0300

    app: add progressive performance logs
    
    Add an option to record progressive performance logs.  Progressive
    logs contain complete information after each recorded sample, by
    writing partial address maps at each sample, containing all new
    addresses introduced by the sample.  Furthermore, when recording a
    progressive log, the output stream is flushed after each sample.
    
    This allows recording complete logs even in cases where they can't
    be properly terminated, such as when GIMP crashes or freezes in the
    middle of the log.
    
    Progressive logs are disabled by default, since they potentially
    increase the sampling cost.  They can be enabled through a toggle
    in the log file-dialog, or through the
    GIMP_PERFORMANCE_LOG_PROGRESSIVE environment varaible.
    
    (cherry picked from commit 146c234350d63f2366ee47abf9498412894fe1c9)

 app/actions/dashboard-commands.c |  14 +++++
 app/widgets/gimpdashboard.c      | 128 +++++++++++++++++++++++++++++----------
 app/widgets/gimpdashboard.h      |   1 +
 3 files changed, 110 insertions(+), 33 deletions(-)
---
diff --git a/app/actions/dashboard-commands.c b/app/actions/dashboard-commands.c
index 76058c59f0..8e349a558e 100644
--- a/app/actions/dashboard-commands.c
+++ b/app/actions/dashboard-commands.c
@@ -212,6 +212,20 @@ dashboard_log_record_cmd_callback (GimpAction *action,
                             G_CALLBACK (gimp_toggle_button_update),
                             &info->params.backtrace);
 
+          toggle = gtk_check_button_new_with_mnemonic (_("Progressi_ve"));
+          gimp_help_set_help_data (toggle, _("Produce complete log "
+                                             "even if not properly terminated"),
+                                   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.progressive);
+
+          g_signal_connect (toggle, "toggled",
+                            G_CALLBACK (gimp_toggle_button_update),
+                            &info->params.progressive);
+
           g_signal_connect (dialog, "response",
                             G_CALLBACK (dashboard_log_record_response),
                             dashboard);
diff --git a/app/widgets/gimpdashboard.c b/app/widgets/gimpdashboard.c
index ed8bb3eaab..fb9def64a8 100644
--- a/app/widgets/gimpdashboard.c
+++ b/app/widgets/gimpdashboard.c
@@ -99,6 +99,7 @@
 #define LOG_SAMPLE_FREQUENCY_MAX       1000 /* samples per second */
 #define LOG_DEFAULT_SAMPLE_FREQUENCY   10 /* samples per second */
 #define LOG_DEFAULT_BACKTRACE          TRUE
+#define LOG_DEFAULT_PROGRESSIVE        FALSE
 
 
 typedef enum
@@ -440,7 +441,11 @@ static void       gimp_dashboard_log_sample                     (GimpDashboard
 static void       gimp_dashboard_log_update_highlight           (GimpDashboard       *dashboard);
 static void       gimp_dashboard_log_update_n_markers           (GimpDashboard       *dashboard);
 
-static void       gimp_dashboard_log_write_address_map          (GimpAsync           *async,
+static void       gimp_dashboard_log_write_address_map          (GimpDashboard       *dashboard,
+                                                                 guintptr            *addresses,
+                                                                 gint                 n_addresses,
+                                                                 GimpAsync           *async);
+static void       gimp_dashboard_log_write_global_address_map   (GimpAsync           *async,
                                                                  GimpDashboard       *dashboard);
 
 static gboolean   gimp_dashboard_field_use_meter_underlay       (Group                group,
@@ -3556,6 +3561,7 @@ gimp_dashboard_log_sample (GimpDashboard *dashboard,
 {
   GimpDashboardPrivate *priv      = dashboard->priv;
   GimpBacktrace        *backtrace = NULL;
+  GArray               *addresses = NULL;
   gboolean              empty     = TRUE;
   Variable              variable;
 
@@ -3874,7 +3880,18 @@ gimp_dashboard_log_sample (GimpDashboard *dashboard,
                                              "<frame address=\"0x%llx\" />\n",
                                              (unsigned long long) address);
 
-                  g_hash_table_add (priv->log_addresses, (gpointer) address);
+                  if (g_hash_table_add (priv->log_addresses,
+                                        (gpointer) address) &&
+                      priv->log_params.progressive)
+                    {
+                      if (! addresses)
+                        {
+                          addresses = g_array_new (FALSE, FALSE,
+                                                   sizeof (guintptr));
+                        }
+
+                      g_array_append_val (addresses, address);
+                    }
                 }
 
               gimp_dashboard_log_printf (dashboard,
@@ -3917,6 +3934,19 @@ gimp_dashboard_log_sample (GimpDashboard *dashboard,
                                  "</sample>\n");
     }
 
+  if (addresses)
+    {
+      gimp_dashboard_log_write_address_map (dashboard,
+                                            (guintptr *) addresses->data,
+                                            addresses->len,
+                                            NULL);
+
+      g_array_free (addresses, TRUE);
+    }
+
+  if (priv->log_params.progressive)
+    g_output_stream_flush (priv->log_output, NULL, NULL);
+
   #undef NONEMPTY
 
   priv->log_n_samples++;
@@ -3959,34 +3989,17 @@ gimp_dashboard_log_compare_addresses (gconstpointer a1,
 }
 
 static void
-gimp_dashboard_log_write_address_map (GimpAsync     *async,
-                                      GimpDashboard *dashboard)
+gimp_dashboard_log_write_address_map (GimpDashboard *dashboard,
+                                      guintptr      *addresses,
+                                      gint           n_addresses,
+                                      GimpAsync     *async)
 {
-  GimpDashboardPrivate     *priv = dashboard->priv;
-  GimpBacktraceAddressInfo  infos[2];
-  guintptr                 *addresses;
-  gint                      n_addresses;
-  GList                    *iter;
-  gint                      i;
-  gint                      n;
-
-  n_addresses = g_hash_table_size (priv->log_addresses);
+  GimpBacktraceAddressInfo infos[2];
+  gint                     i;
+  gint                     n;
 
   if (n_addresses == 0)
-    {
-      gimp_async_finish (async, NULL);
-
-      return;
-    }
-
-  addresses = g_new (guintptr, n_addresses);
-
-  for (iter = g_hash_table_get_keys (priv->log_addresses), i = 0;
-       iter;
-       iter = g_list_next (iter), i++)
-    {
-      addresses[i] = (guintptr) iter->data;
-    }
+    return;
 
   qsort (addresses, n_addresses, sizeof (guintptr),
          gimp_dashboard_log_compare_addresses);
@@ -4002,7 +4015,7 @@ gimp_dashboard_log_write_address_map (GimpAsync     *async,
       GimpBacktraceAddressInfo       *info      = &infos[n       % 2];
       const GimpBacktraceAddressInfo *prev_info = &infos[(n + 1) % 2];
 
-      if (gimp_async_is_canceled (async))
+      if (async && gimp_async_is_canceled (async))
         break;
 
       if (gimp_backtrace_get_address_info (addresses[i], info))
@@ -4139,11 +4152,41 @@ gimp_dashboard_log_write_address_map (GimpAsync     *async,
         }
     }
 
-  g_free (addresses);
-
   gimp_dashboard_log_printf (dashboard,
                              "\n"
                              "</address-map>\n");
+}
+
+static void
+gimp_dashboard_log_write_global_address_map (GimpAsync     *async,
+                                             GimpDashboard *dashboard)
+{
+  GimpDashboardPrivate *priv = dashboard->priv;
+  gint                  n_addresses;
+
+  n_addresses = g_hash_table_size (priv->log_addresses);
+
+  if (n_addresses > 0)
+    {
+      guintptr *addresses;
+      GList    *iter;
+      gint      i;
+
+      addresses = g_new (guintptr, n_addresses);
+
+      for (iter = g_hash_table_get_keys (priv->log_addresses), i = 0;
+           iter;
+           iter = g_list_next (iter), i++)
+        {
+          addresses[i] = (guintptr) iter->data;
+        }
+
+      gimp_dashboard_log_write_address_map (dashboard,
+                                            addresses, n_addresses,
+                                            async);
+
+      g_free (addresses);
+    }
 
   gimp_async_finish (async, NULL);
 }
@@ -4331,12 +4374,27 @@ gimp_dashboard_log_start_recording (GimpDashboard                 *dashboard,
         atoi (g_getenv ("GIMP_PERFORMANCE_LOG_BACKTRACE")) ? 1 : 0;
     }
 
+  if (g_getenv ("GIMP_PERFORMANCE_LOG_PROGRESSIVE"))
+    {
+      priv->log_params.progressive =
+        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);
 
+  if (priv->log_params.progressive     &&
+      g_file_query_exists (file, NULL) &&
+      ! g_file_delete (file, NULL, error))
+    {
+      g_mutex_unlock (&priv->mutex);
+
+      return FALSE;
+    }
+
   priv->log_output = G_OUTPUT_STREAM (g_file_replace (file,
                                       NULL, FALSE, G_FILE_CREATE_NONE, NULL,
                                       error));
@@ -4370,9 +4428,11 @@ gimp_dashboard_log_start_recording (GimpDashboard                 *dashboard,
                              "<params>\n"
                              "<sample-frequency>%d</sample-frequency>\n"
                              "<backtrace>%d</backtrace>\n"
+                             "<progressive>%d</progressive>\n"
                              "</params>\n",
                              priv->log_params.sample_frequency,
-                             has_backtrace);
+                             has_backtrace,
+                             priv->log_params.progressive);
 
   gimp_dashboard_log_printf (dashboard,
                              "\n"
@@ -4580,12 +4640,13 @@ gimp_dashboard_log_stop_recording (GimpDashboard  *dashboard,
                              "</samples>\n");
 
 
-  if (g_hash_table_size (priv->log_addresses) > 0)
+  if (! priv->log_params.progressive &&
+      g_hash_table_size (priv->log_addresses) > 0)
     {
       GimpAsync *async;
 
       async = gimp_parallel_run_async_independent (
-        (GimpRunAsyncFunc) gimp_dashboard_log_write_address_map,
+        (GimpRunAsyncFunc) gimp_dashboard_log_write_global_address_map,
         dashboard);
 
       gimp_wait (priv->gimp, GIMP_WAITABLE (async),
@@ -4659,6 +4720,7 @@ gimp_dashboard_log_get_default_params (GimpDashboard *dashboard)
   {
     .sample_frequency = LOG_DEFAULT_SAMPLE_FREQUENCY,
     .backtrace        = LOG_DEFAULT_BACKTRACE,
+    .progressive      = LOG_DEFAULT_PROGRESSIVE
   };
 
   g_return_val_if_fail (GIMP_IS_DASHBOARD (dashboard), NULL);
diff --git a/app/widgets/gimpdashboard.h b/app/widgets/gimpdashboard.h
index 3a5b639aa4..136b39e86e 100644
--- a/app/widgets/gimpdashboard.h
+++ b/app/widgets/gimpdashboard.h
@@ -29,6 +29,7 @@ struct _GimpDashboardLogParams
 {
   gint     sample_frequency;
   gboolean backtrace;
+  gboolean progressive;
 };
 
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]