From feecf8b88f7a46bc25f648dbb874f9165e2baa77 Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 27 May 2009 20:40:50 -0400 Subject: [PATCH 4/4] Correct startup flaw in idle swapper start: Don't watch only UI idling, but also watch that the cache itself is idle. Previously it would start during transforms and long pyramid rendering ops and toss writes and large seeks into the tile cache while it was potentially under heavy pressure. Also increase its flush rate more to be more in line with modern system and editing needs. --- app/base/tile-cache.c | 105 ++++++++++++++++++++++++++++++++++++------------- app/base/tile-cache.h | 1 + app/base/tile-swap.c | 5 ++- 3 files changed, 82 insertions(+), 29 deletions(-) diff --git a/app/base/tile-cache.c b/app/base/tile-cache.c index 8c8e8cf..4fb7f87 100644 --- a/app/base/tile-cache.c +++ b/app/base/tile-cache.c @@ -27,17 +27,15 @@ #include "tile-rowhints.h" #include "tile-private.h" - -#define IDLE_SWAPPER_TIMEOUT 250 - +#define IDLE_SWAPPER_START 1000 +#define IDLE_SWAPPER_INTERVAL_MS 20 +#define IDLE_SWAPPER_TILES_PER_INTERVAL 10 static gboolean tile_cache_zorch_next (void); static void tile_cache_flush_internal (Tile *tile); - static gboolean tile_idle_preswap (gpointer data); static void tile_verify(void); - typedef struct _TileList { Tile *first; @@ -49,6 +47,7 @@ static gulong max_cache_size = 0; static gulong cur_cache_dirty = 0; static TileList tile_list = { NULL, NULL }; static guint idle_swapper = 0; +static guint idle_delay = 0; static Tile *idle_scan_last = NULL; #ifdef TILE_PROFILING @@ -112,6 +111,12 @@ tile_cache_exit (void) } void +tile_cache_suspend_idle_swapper(void) +{ + idle_delay = 1; +} + +void tile_cache_insert (Tile *tile) { @@ -208,6 +213,7 @@ tile_cache_insert (Tile *tile) } tile_list.last = tile; tile->cached = TRUE; + idle_delay = 1; if (PENDING_WRITE(tile)) { @@ -216,15 +222,16 @@ tile_cache_insert (Tile *tile) if(!idle_scan_last) idle_scan_last=tile; - if (! idle_swapper && - cur_cache_dirty * 2 > max_cache_size) + if (!idle_swapper) { #ifdef TILE_PROFILING - g_printerr("idle swapper -> running"); + g_printerr("idle swapper -> started\n"); + g_printerr("idle swapper -> waiting"); #endif + idle_delay = 0; idle_swapper = g_timeout_add_full (G_PRIORITY_LOW, - IDLE_SWAPPER_TIMEOUT, + IDLE_SWAPPER_START, tile_idle_preswap, NULL, NULL); } @@ -250,6 +257,7 @@ tile_cache_set_size (gulong cache_size) { TILE_CACHE_LOCK; + idle_delay = 1; max_cache_size = cache_size; while (cur_cache_size > max_cache_size) @@ -309,6 +317,7 @@ tile_cache_zorch_next (void) if (PENDING_WRITE(tile)) { + idle_delay = 1; tile_swap_out (tile); } @@ -327,52 +336,92 @@ tile_cache_zorch_next (void) } static gboolean -tile_idle_preswap (gpointer data) +tile_idle_preswap_run (gpointer data) { Tile *tile; + int count = 0; - if (cur_cache_dirty * 2 < max_cache_size) + if (idle_delay) { #ifdef TILE_PROFILING - g_printerr("\nidle swapper -> stopped\n"); + g_printerr("\nidle swapper -> waiting"); #endif - idle_swapper = 0; + idle_delay = 0; + idle_swapper = g_timeout_add_full (G_PRIORITY_LOW, + IDLE_SWAPPER_START, + tile_idle_preswap, + NULL, NULL); return FALSE; } TILE_CACHE_LOCK; #ifdef TILE_PROFILING - tile_verify(); g_printerr("."); - tile_idle_swapout++; #endif tile = idle_scan_last; - while(tile){ - if(PENDING_WRITE(tile)){ - idle_scan_last = tile->next; - - tile_swap_out (tile); - if(!PENDING_WRITE(tile)) - cur_cache_dirty -= tile->size; - - TILE_CACHE_UNLOCK; - return TRUE; + while(tile) + { + if(PENDING_WRITE(tile)) + { + idle_scan_last = tile->next; + +#ifdef TILE_PROFILING + tile_idle_swapout++; +#endif + tile_swap_out (tile); + if(!PENDING_WRITE(tile)) + cur_cache_dirty -= tile->size; + count++; + + if(count>=IDLE_SWAPPER_TILES_PER_INTERVAL) + { + TILE_CACHE_UNLOCK; + return TRUE; + } + } + tile = tile->next; } - tile = tile->next; - } g_printerr("\nidle swapper -> stopped\n"); idle_scan_last = NULL; idle_swapper = 0; - + +#ifdef TILE_PROFILING + tile_verify(); +#endif + TILE_CACHE_UNLOCK; return FALSE; } +static gboolean +tile_idle_preswap (gpointer data) +{ + + if (idle_delay){ +#ifdef TILE_PROFILING + g_printerr("."); +#endif + idle_delay = 0; + return TRUE; + } + +#ifdef TILE_PROFILING + tile_verify(); + g_printerr("\nidle swapper -> running"); +#endif + + idle_swapper = g_timeout_add_full (G_PRIORITY_LOW, + IDLE_SWAPPER_INTERVAL_MS, + tile_idle_preswap_run, + NULL, NULL); + return FALSE; +} + #ifdef TILE_PROFILING static void tile_verify(void) diff --git a/app/base/tile-cache.h b/app/base/tile-cache.h index 3128150..09ba4e2 100644 --- a/app/base/tile-cache.h +++ b/app/base/tile-cache.h @@ -23,6 +23,7 @@ void tile_cache_init (gulong cache_size); void tile_cache_exit (void); void tile_cache_set_size (gulong cache_size); +void tile_cache_suspend_idle_swapper(void); void tile_cache_insert (Tile *tile); void tile_cache_flush (Tile *tile); diff --git a/app/base/tile-swap.c b/app/base/tile-swap.c index b19d211..6953867 100644 --- a/app/base/tile-swap.c +++ b/app/base/tile-swap.c @@ -50,6 +50,7 @@ #include "tile-rowhints.h" #include "tile-swap.h" #include "tile-private.h" +#include "tile-cache.h" #include "gimp-intl.h" @@ -374,7 +375,9 @@ tile_swap_default_in (SwapFile *swap_file, if (tile->data) return; -#ifdef TILE_PROFILING + tile_cache_suspend_idle_swapper(); + +#ifdef TILE_PROFILING g_get_current_time(&now); tile_total_swapin++; -- 1.6.3.1