[gtk/wip/chergert/tune-linedisplay-cache] textview: optimize linedisplay cache based on number of visible rows



commit 5e49da1d73534e45e3139d7ded740f3115b7096f
Author: Christian Hergert <chergert redhat com>
Date:   Thu Sep 5 16:45:49 2019 -0700

    textview: optimize linedisplay cache based on number of visible rows
    
    This tries to estimate the number of visible rows in a textview based on
    the default text size and then tunes the GtkTextLineDisplayCache to keep
    3*n_rows entries in the cache.
    
    This was found imperically to be near the right cache size. In most cases,
    this is less than the number of items we cache now. However, in some cases,
    such as the "overview map" from GtkSourceView, it allows us to reach a
    higher value such as 1000+. This is needed to keep scrolling smooth on
    the larger view sizes.
    
    With this patch, a HiDPI system with a GtkSourceView and GtkSourceMap
    from the GTK 4 port can perform smooth scrolling simultaneously.

 gtk/gtktextlayout.c                  |  9 +++++++++
 gtk/gtktextlayoutprivate.h           |  3 +++
 gtk/gtktextlinedisplaycache.c        | 30 ++++++++++++++++++++++++++++--
 gtk/gtktextlinedisplaycacheprivate.h |  2 ++
 gtk/gtktextview.c                    | 12 ++++++++++++
 5 files changed, 54 insertions(+), 2 deletions(-)
---
diff --git a/gtk/gtktextlayout.c b/gtk/gtktextlayout.c
index fee6d59a4a..f51dd42fcb 100644
--- a/gtk/gtktextlayout.c
+++ b/gtk/gtktextlayout.c
@@ -4210,3 +4210,12 @@ gtk_text_line_display_compare (const GtkTextLineDisplay *display1,
   else
     return 0;
 }
+
+void
+gtk_text_layout_set_mru_size (GtkTextLayout *layout,
+                              guint          mru_size)
+{
+  GtkTextLayoutPrivate *priv = GTK_TEXT_LAYOUT_GET_PRIVATE (layout);
+
+  gtk_text_line_display_cache_set_mru_size (priv->cache, mru_size);
+}
diff --git a/gtk/gtktextlayoutprivate.h b/gtk/gtktextlayoutprivate.h
index 27da15d2bd..99d4f812e8 100644
--- a/gtk/gtktextlayoutprivate.h
+++ b/gtk/gtktextlayoutprivate.h
@@ -414,6 +414,9 @@ void gtk_text_layout_snapshot (GtkTextLayout        *layout,
                                const GdkRectangle   *clip,
                                float                 cursor_alpha);
 
+void gtk_text_layout_set_mru_size (GtkTextLayout *layout,
+                                   guint          mru_size);
+
 G_END_DECLS
 
 #endif  /* __GTK_TEXT_LAYOUT_PRIVATE_H__ */
diff --git a/gtk/gtktextlinedisplaycache.c b/gtk/gtktextlinedisplaycache.c
index 267d9f6182..2fe174c0f6 100644
--- a/gtk/gtktextlinedisplaycache.c
+++ b/gtk/gtktextlinedisplaycache.c
@@ -24,7 +24,7 @@
 #include "gtktextiterprivate.h"
 #include "gtktextlinedisplaycacheprivate.h"
 
-#define MRU_MAX_SIZE             250
+#define DEFAULT_MRU_SIZE         250
 #define BLOW_CACHE_TIMEOUT_SEC   20
 #define DEBUG_LINE_DISPLAY_CACHE 0
 
@@ -35,6 +35,7 @@ struct _GtkTextLineDisplayCache
   GtkTextLine *cursor_line;
   GQueue       mru;
   GSource     *evict_source;
+  guint        mru_size;
 
 #if DEBUG_LINE_DISPLAY_CACHE
   guint       log_source;
@@ -78,6 +79,7 @@ gtk_text_line_display_cache_new (void)
   ret = g_slice_new0 (GtkTextLineDisplayCache);
   ret->sorted_by_line = g_sequence_new ((GDestroyNotify)gtk_text_line_display_unref);
   ret->line_to_display = g_hash_table_new (NULL, NULL);
+  ret->mru_size = DEFAULT_MRU_SIZE;
 
 #if DEBUG_LINE_DISPLAY_CACHE
   ret->log_source = g_timeout_add_seconds (1, dump_stats, ret);
@@ -200,7 +202,7 @@ gtk_text_line_display_cache_take_display (GtkTextLineDisplayCache *cache,
   g_queue_push_head_link (&cache->mru, &display->mru_link);
 
   /* Cull the cache if we're at capacity */
-  while (cache->mru.length > MRU_MAX_SIZE)
+  while (cache->mru.length > cache->mru_size)
     {
       display = g_queue_peek_tail (&cache->mru);
 
@@ -716,3 +718,27 @@ gtk_text_line_display_cache_set_cursor_line (GtkTextLineDisplayCache *cache,
   if (display != NULL)
     gtk_text_line_display_cache_invalidate_display (cache, display, FALSE);
 }
+
+void
+gtk_text_line_display_cache_set_mru_size (GtkTextLineDisplayCache *cache,
+                                          guint                    mru_size)
+{
+  GtkTextLineDisplay *display;
+
+  g_assert (cache != NULL);
+
+  if (mru_size == 0)
+    mru_size = DEFAULT_MRU_SIZE;
+
+  if (mru_size != cache->mru_size)
+    {
+      cache->mru_size = mru_size;
+
+      while (cache->mru.length > cache->mru_size)
+        {
+          display = g_queue_peek_tail (&cache->mru);
+
+          gtk_text_line_display_cache_invalidate_display (cache, display, FALSE);
+        }
+    }
+}
diff --git a/gtk/gtktextlinedisplaycacheprivate.h b/gtk/gtktextlinedisplaycacheprivate.h
index 5639ec2070..89adbffc2d 100644
--- a/gtk/gtktextlinedisplaycacheprivate.h
+++ b/gtk/gtktextlinedisplaycacheprivate.h
@@ -53,6 +53,8 @@ void                     gtk_text_line_display_cache_invalidate_y_range (GtkText
                                                                          gint                     y,
                                                                          gint                     height,
                                                                          gboolean                 
cursors_only);
+void                     gtk_text_line_display_cache_set_mru_size       (GtkTextLineDisplayCache *cache,
+                                                                         guint                    mru_size);
 
 G_END_DECLS
 
diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c
index 6d405df097..1d01f9c454 100644
--- a/gtk/gtktextview.c
+++ b/gtk/gtktextview.c
@@ -4109,6 +4109,8 @@ gtk_text_view_size_allocate (GtkWidget *widget,
   GdkRectangle top_rect;
   GdkRectangle bottom_rect;
   GtkWidget *chooser;
+  PangoLayout *layout;
+  guint mru_size;
   
   text_view = GTK_TEXT_VIEW (widget);
   priv = text_view->priv;
@@ -4178,6 +4180,16 @@ gtk_text_view_size_allocate (GtkWidget *widget,
   if (!gtk_adjustment_is_animating (priv->vadjustment))
     gtk_text_view_set_vadjustment_values (text_view);
 
+  /* Optimize display cache size */
+  layout = gtk_widget_create_pango_layout (widget, "X");
+  pango_layout_get_pixel_size (layout, &width, &height);
+  if (height > 0)
+    {
+      mru_size = SCREEN_HEIGHT (widget) / height * 3;
+      gtk_text_layout_set_mru_size (priv->layout, mru_size);
+    }
+  g_object_unref (layout);
+
   /* The GTK resize loop processes all the pending exposes right
    * after doing the resize stuff, so the idle sizer won't have a
    * chance to run. So we do the work here. 


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