[gegl] gegl: add GeglStats object, gegl_stats() function



commit f5f31ba4a132779b4bebc2bf990a53edbad815f5
Author: Ell <ell_se yahoo com>
Date:   Mon Dec 18 19:24:07 2017 -0500

    gegl: add GeglStats object, gegl_stats() function
    
    The GeglStats object provides a set of read-only properties, aimed
    at monitoring GEGL statistics.  The singleton GeglStats instance is
    returned by gegl_stats(), in a similar fashion to gegl_config().
    
    The following properties are currently implemented:
    
      - cache-total:  The total size of the data in the cache.
    
      - swap-total:  The total size of the data in the swap.
    
      - swap-file-size:  The size of the swap file.
    
      - swap-busy:  Whether there is work queued for the swap.

 gegl/Makefile.am                      |    2 +
 gegl/buffer/gegl-tile-backend-swap.c  |   68 ++++++++++++----
 gegl/buffer/gegl-tile-backend-swap.h  |    6 +-
 gegl/buffer/gegl-tile-handler-cache.c |    6 ++
 gegl/buffer/gegl-tile-handler-cache.h |    2 +
 gegl/gegl-init.c                      |   11 +++
 gegl/gegl-init.h                      |   10 +++
 gegl/gegl-stats.c                     |  138 +++++++++++++++++++++++++++++++++
 gegl/gegl-stats.h                     |   46 +++++++++++
 gegl/gegl-types.h                     |    6 ++
 10 files changed, 278 insertions(+), 17 deletions(-)
---
diff --git a/gegl/Makefile.am b/gegl/Makefile.am
index 8da4e02..c139754 100644
--- a/gegl/Makefile.am
+++ b/gegl/Makefile.am
@@ -98,6 +98,7 @@ GEGL_sources = \
        gegl-gio.c                      \
        gegl-random.c                   \
        gegl-serialize.c                \
+       gegl-stats.c                    \
        gegl-matrix.c                   \
        \
        gegl-algorithms.h \
@@ -115,6 +116,7 @@ GEGL_sources = \
        gegl-op.h                           \
        gegl-plugin.h                   \
        gegl-random-private.h           \
+       gegl-stats.h                    \
        gegl-gio-private.h              \
        gegl-types-internal.h           \
        gegl-xml.h
diff --git a/gegl/buffer/gegl-tile-backend-swap.c b/gegl/buffer/gegl-tile-backend-swap.c
index f7b6364..40a7746 100644
--- a/gegl/buffer/gegl-tile-backend-swap.c
+++ b/gegl/buffer/gegl-tile-backend-swap.c
@@ -147,13 +147,15 @@ static void        gegl_tile_backend_swap_init          (GeglTileBackendSwap *se
 void               gegl_tile_backend_swap_cleanup       (void);
 
 
-static gchar  *path       = NULL;
-static gint    in_fd      = -1;
-static gint    out_fd     = -1;
-static gint64  in_offset  = 0;
-static gint64  out_offset = 0;
-static GList  *gap_list   = NULL;
-static gint64  total      = 0;
+static gchar    *path       = NULL;
+static gint      in_fd      = -1;
+static gint      out_fd     = -1;
+static gint64    in_offset  = 0;
+static gint64    out_offset = 0;
+static GList    *gap_list   = NULL;
+static gint64    file_size  = 0;
+static gint64    total      = 0;
+static gboolean  busy       = FALSE;
 
 static GThread      *writer_thread = NULL;
 static GQueue       *queue         = NULL;
@@ -168,6 +170,8 @@ static void
 gegl_tile_backend_swap_push_queue (ThreadParams *params,
                                    gboolean      head)
 {
+  busy = TRUE;
+
   if (head)
     g_queue_push_head (queue, params);
   else
@@ -183,15 +187,15 @@ gegl_tile_backend_swap_push_queue (ThreadParams *params,
 static void
 gegl_tile_backend_swap_resize (gint64 size)
 {
-  total = size;
+  file_size = size;
 
-  if (ftruncate (out_fd, total) != 0)
+  if (ftruncate (out_fd, file_size) != 0)
     {
       g_warning ("failed to resize swap file: %s", g_strerror (errno));
       return;
     }
 
-  GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "resized swap to %i", (gint)total);
+  GEGL_NOTE (GEGL_DEBUG_TILE_BACKEND, "resized swap to %i", (gint)file_size);
 }
 
 static SwapGap *
@@ -212,6 +216,8 @@ gegl_tile_backend_swap_find_offset (gint tile_size)
   SwapGap *gap;
   gint64   offset;
 
+  total += tile_size;
+
   if (gap_list)
     {
       GList *link = gap_list;
@@ -243,11 +249,11 @@ gegl_tile_backend_swap_find_offset (gint tile_size)
         }
     }
 
-  offset = total;
+  offset = file_size;
 
-  gegl_tile_backend_swap_resize (total + 32 * tile_size);
+  gegl_tile_backend_swap_resize (file_size + 32 * tile_size);
 
-  gap = gegl_tile_backend_swap_gap_new (offset + tile_size, total);
+  gap = gegl_tile_backend_swap_gap_new (offset + tile_size, file_size);
   gap_list = g_list_append (gap_list, gap);
 
   return offset;
@@ -387,6 +393,8 @@ gegl_tile_backend_swap_destroy (ThreadParams *params)
   else
     gap_list = g_list_prepend (NULL,
                                gegl_tile_backend_swap_gap_new (start, end));
+
+  total -= end - start;
 }
 
 static gpointer
@@ -399,7 +407,11 @@ gegl_tile_backend_swap_writer_thread (gpointer ignored)
       ThreadParams *params;
 
       while (g_queue_is_empty (queue) && !exit_thread)
-        g_cond_wait (&queue_cond, &queue_mutex);
+        {
+          busy = FALSE;
+
+          g_cond_wait (&queue_cond, &queue_mutex);
+        }
 
       if (exit_thread)
         break;
@@ -904,13 +916,13 @@ gegl_tile_backend_swap_cleanup (void)
           if (gap_list->next)
             g_warning ("tile-backend-swap gap list had more than one element\n");
 
-          g_warn_if_fail (gap->start == 0 && gap->end == total);
+          g_warn_if_fail (gap->start == 0 && gap->end == file_size);
 
           g_slice_free (SwapGap, gap_list->data);
           g_list_free (gap_list);
         }
       else
-        g_warn_if_fail (total == 0);
+        g_warn_if_fail (file_size == 0);
 
       close (in_fd);
       close (out_fd);
@@ -927,3 +939,27 @@ gegl_tile_backend_swap_init (GeglTileBackendSwap *self)
   self->index = g_hash_table_new (gegl_tile_backend_swap_hashfunc,
                                   gegl_tile_backend_swap_equalfunc);
 }
+
+/* the following functions could theoretically return slightly wrong values on
+ * 32-bit platforms, due to non-atomic 64-bit access, but since it's not too
+ * important for these functions to be completely accurate at all times, it
+ * should be ok.
+ */
+ 
+guint64
+gegl_tile_backend_swap_get_total (void)
+{
+  return total;
+}
+
+guint64
+gegl_tile_backend_swap_get_file_size (void)
+{
+  return file_size;
+}
+
+gboolean
+gegl_tile_backend_swap_get_busy (void)
+{
+  return busy;
+}
diff --git a/gegl/buffer/gegl-tile-backend-swap.h b/gegl/buffer/gegl-tile-backend-swap.h
index 87a98f1..def9b4a 100644
--- a/gegl/buffer/gegl-tile-backend-swap.h
+++ b/gegl/buffer/gegl-tile-backend-swap.h
@@ -46,7 +46,11 @@ struct _GeglTileBackendSwap
   GHashTable      *index;
 };
 
-GType gegl_tile_backend_swap_get_type (void) G_GNUC_CONST;
+GType      gegl_tile_backend_swap_get_type      (void) G_GNUC_CONST;
+
+guint64    gegl_tile_backend_swap_get_total     (void);
+guint64    gegl_tile_backend_swap_get_file_size (void);
+gboolean   gegl_tile_backend_swap_get_busy      (void);
 
 G_END_DECLS
 
diff --git a/gegl/buffer/gegl-tile-handler-cache.c b/gegl/buffer/gegl-tile-handler-cache.c
index 3bc0132..a41442c 100644
--- a/gegl/buffer/gegl-tile-handler-cache.c
+++ b/gegl/buffer/gegl-tile-handler-cache.c
@@ -632,6 +632,12 @@ gegl_tile_handler_cache_new (void)
   return g_object_new (GEGL_TYPE_TILE_HANDLER_CACHE, NULL);
 }
 
+gsize
+gegl_tile_handler_cache_get_total (void)
+{
+  return cache_total;
+}
+
 
 static guint
 gegl_tile_handler_cache_hashfunc (gconstpointer key)
diff --git a/gegl/buffer/gegl-tile-handler-cache.h b/gegl/buffer/gegl-tile-handler-cache.h
index 00a69f1..913340a 100644
--- a/gegl/buffer/gegl-tile-handler-cache.h
+++ b/gegl/buffer/gegl-tile-handler-cache.h
@@ -61,4 +61,6 @@ void              gegl_tile_handler_cache_insert        (GeglTileHandlerCache *c
 void              gegl_tile_handler_cache_tile_uncloned (GeglTileHandlerCache *cache,
                                                          GeglTile             *tile);
 
+gsize             gegl_tile_handler_cache_get_total     (void);
+
 #endif
diff --git a/gegl/gegl-init.c b/gegl/gegl-init.c
index 3df8ac6..06bd450 100644
--- a/gegl/gegl-init.c
+++ b/gegl/gegl-init.c
@@ -102,6 +102,7 @@ guint gegl_debug_flags = 0;
 #include "buffer/gegl-tile-backend-ram.h"
 #include "buffer/gegl-tile-backend-file.h"
 #include "gegl-config.h"
+#include "gegl-stats.h"
 #include "graph/gegl-node-private.h"
 #include "gegl-random-private.h"
 
@@ -113,6 +114,8 @@ static gboolean  gegl_post_parse_hook (GOptionContext *context,
 
 static GeglConfig   *config = NULL;
 
+static GeglStats    *stats = NULL;
+
 static GeglModuleDB *module_db   = NULL;
 
 static glong         global_time = 0;
@@ -415,6 +418,14 @@ GeglConfig *gegl_config (void)
   return config;
 }
 
+GeglStats *gegl_stats (void)
+{
+  if (! stats)
+    stats = g_object_new (GEGL_TYPE_STATS, NULL);
+
+  return stats;
+}
+
 static void swap_clean (void)
 {
   const gchar  *swap_dir = gegl_swap_dir ();
diff --git a/gegl/gegl-init.h b/gegl/gegl-init.h
index 2f80d5a..38cb913 100644
--- a/gegl/gegl-init.h
+++ b/gegl/gegl-init.h
@@ -94,6 +94,16 @@ void          gegl_load_module_directory (const gchar *path);
  */
 GeglConfig   *gegl_config                (void);
 
+/**
+ * gegl_stats:
+ *
+ * Returns a GeglStats object with properties that can be read to monitor
+ * GEGL statistics.
+ *
+ * Return value: (transfer none): a #GeglStats
+ */
+GeglStats    *gegl_stats                 (void);
+
 gboolean gegl_is_main_thread (void);
 
 G_END_DECLS
diff --git a/gegl/gegl-stats.c b/gegl/gegl-stats.c
new file mode 100644
index 0000000..ab82926
--- /dev/null
+++ b/gegl/gegl-stats.c
@@ -0,0 +1,138 @@
+/* This file is part of GEGL.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright 2017 Ell
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+
+#include "gegl.h"
+#include "gegl-types-internal.h"
+#include "buffer/gegl-buffer-types.h"
+#include "buffer/gegl-tile-handler-cache.h"
+#include "buffer/gegl-tile-backend-swap.h"
+#include "gegl-stats.h"
+
+
+enum
+{
+  PROP_0,
+  PROP_TILE_CACHE_TOTAL,
+  PROP_SWAP_TOTAL,
+  PROP_SWAP_FILE_SIZE,
+  PROP_SWAP_BUSY
+};
+
+
+static void   gegl_stats_set_property (GObject      *object,
+                                       guint         property_id,
+                                       const GValue *value,
+                                       GParamSpec   *pspec);
+static void   gegl_stats_get_property (GObject      *object,
+                                       guint         property_id,
+                                       GValue       *value,
+                                       GParamSpec   *pspec);
+
+
+G_DEFINE_TYPE (GeglStats, gegl_stats, G_TYPE_OBJECT)
+
+
+static void
+gegl_stats_class_init (GeglStatsClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->set_property = gegl_stats_set_property;
+  object_class->get_property = gegl_stats_get_property;
+
+  g_object_class_install_property (object_class, PROP_TILE_CACHE_TOTAL,
+                                   g_param_spec_uint64 ("tile-cache-total",
+                                                        "Tile Cache total size",
+                                                        "Total size of tile cache in bytes",
+                                                        0, G_MAXUINT64, 0,
+                                                        G_PARAM_READABLE));
+
+  g_object_class_install_property (object_class, PROP_SWAP_TOTAL,
+                                   g_param_spec_uint64 ("swap-total",
+                                                        "Swap total size",
+                                                        "Total size of the data in the swap",
+                                                        0, G_MAXUINT64, 0,
+                                                        G_PARAM_READABLE));
+
+  g_object_class_install_property (object_class, PROP_SWAP_FILE_SIZE,
+                                   g_param_spec_uint64 ("swap-file-size",
+                                                        "Swap file size",
+                                                        "Size of the swap file",
+                                                        0, G_MAXUINT64, 0,
+                                                        G_PARAM_READABLE));
+
+  g_object_class_install_property (object_class, PROP_SWAP_BUSY,
+                                   g_param_spec_boolean ("swap-busy",
+                                                         "Swap busy",
+                                                         "Whether there is work queued for the swap",
+                                                         FALSE,
+                                                         G_PARAM_READABLE));
+}
+
+static void
+gegl_stats_init (GeglStats *self)
+{
+}
+
+static void
+gegl_stats_set_property (GObject      *object,
+                         guint         property_id,
+                         const GValue *value,
+                         GParamSpec   *pspec)
+{
+  switch (property_id)
+    {
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
+}
+
+static void
+gegl_stats_get_property (GObject    *object,
+                         guint       property_id,
+                         GValue     *value,
+                         GParamSpec *pspec)
+{
+  switch (property_id)
+    {
+      case PROP_TILE_CACHE_TOTAL:
+        g_value_set_uint64 (value, gegl_tile_handler_cache_get_total ());
+        break;
+
+      case PROP_SWAP_TOTAL:
+        g_value_set_uint64 (value, gegl_tile_backend_swap_get_total ());
+        break;
+
+      case PROP_SWAP_FILE_SIZE:
+        g_value_set_uint64 (value, gegl_tile_backend_swap_get_file_size ());
+        break;
+
+      case PROP_SWAP_BUSY:
+        g_value_set_boolean (value, gegl_tile_backend_swap_get_busy ());
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
+}
diff --git a/gegl/gegl-stats.h b/gegl/gegl-stats.h
new file mode 100644
index 0000000..c521703
--- /dev/null
+++ b/gegl/gegl-stats.h
@@ -0,0 +1,46 @@
+/* This file is part of GEGL.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright 2017 Ell
+ */
+
+#ifndef __GEGL_STATS_H__
+#define __GEGL_STATS_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GEGL_STATS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  GEGL_TYPE_STATS, GeglStatsClass))
+#define GEGL_IS_STATS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  GEGL_TYPE_STATS))
+#define GEGL_STATS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),  GEGL_TYPE_STATS, GeglStatsClass))
+/* The rest is in gegl-types.h */
+
+typedef struct _GeglStatsClass GeglStatsClass;
+
+struct _GeglStats
+{
+  GObject  parent_instance;
+};
+
+struct _GeglStatsClass
+{
+  GObjectClass  parent_class;
+};
+
+G_END_DECLS
+
+#endif
diff --git a/gegl/gegl-types.h b/gegl/gegl-types.h
index 743b51e..81a0d8a 100644
--- a/gegl/gegl-types.h
+++ b/gegl/gegl-types.h
@@ -55,6 +55,12 @@ GType gegl_config_get_type (void) G_GNUC_CONST;
 #define GEGL_CONFIG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEGL_TYPE_CONFIG, GeglConfig))
 #define GEGL_IS_CONFIG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEGL_TYPE_CONFIG))
 
+typedef struct _GeglStats GeglStats;
+GType gegl_stats_get_type (void) G_GNUC_CONST;
+#define GEGL_TYPE_STATS             (gegl_stats_get_type ())
+#define GEGL_STATS(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEGL_TYPE_STATS, GeglStats))
+#define GEGL_IS_STATS(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEGL_TYPE_STATS))
+
 typedef struct _GeglSampler       GeglSampler;
 typedef struct _GeglCurve         GeglCurve;
 typedef struct _GeglPath          GeglPath;


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