Mercurial > emacs
changeset 108741:9480d787845f
Improve image cache clearing logic (Bug#6230).
* xdisp.c (redisplay_internal): Clear caches even if redisplaying
just one window.
* image.c (Vimage_cache_eviction_delay): Decrease to 300.
(clear_image_cache): If the number of cached images is unusually
large, decrease the cache eviction delay.
author | Chong Yidong <cyd@stupidchicken.com> |
---|---|
date | Fri, 21 May 2010 13:29:27 -0400 |
parents | e6ab17110c0d |
children | 36dd9f97c404 |
files | src/ChangeLog src/image.c src/xdisp.c |
diffstat | 3 files changed, 78 insertions(+), 36 deletions(-) [+] |
line wrap: on
line diff
--- a/src/ChangeLog Fri May 21 09:31:45 2010 -0700 +++ b/src/ChangeLog Fri May 21 13:29:27 2010 -0400 @@ -1,3 +1,12 @@ +2010-05-21 Chong Yidong <cyd@stupidchicken.com> + + * xdisp.c (redisplay_internal): Clear caches even if redisplaying + just one window. + + * image.c (Vimage_cache_eviction_delay): Decrease to 300. + (clear_image_cache): If the number of cached images is unusually + large, decrease the cache eviction delay (Bug#6230). + 2010-05-21 Glenn Morris <rgm@gnu.org> * Makefile.in (${ns_appdir}, ${ns_appbindir}Emacs, ns-app):
--- a/src/image.c Fri May 21 09:31:45 2010 -0700 +++ b/src/image.c Fri May 21 13:29:27 2010 -0400 @@ -1582,29 +1582,56 @@ { struct image_cache *c = FRAME_IMAGE_CACHE (f); - if (c && (!NILP (filter) || INTEGERP (Vimage_cache_eviction_delay))) - { - EMACS_TIME t; - unsigned long old; - int i, nfreed; - - EMACS_GET_TIME (t); - old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay); + if (c) + { + int i, nfreed = 0; /* Block input so that we won't be interrupted by a SIGIO while being in an inconsistent state. */ BLOCK_INPUT; - for (i = nfreed = 0; i < c->used; ++i) + if (!NILP (filter)) + { + /* Filter image cache. */ + for (i = 0; i < c->used; ++i) + { + struct image *img = c->images[i]; + if (img && (EQ (Qt, filter) + || !NILP (Fmember (filter, img->dependencies)))) + { + free_image (f, img); + ++nfreed; + } + } + } + else if (INTEGERP (Vimage_cache_eviction_delay)) { - struct image *img = c->images[i]; - if (img != NULL - && (NILP (filter) ? img->timestamp < old - : (EQ (Qt, filter) - || !NILP (Fmember (filter, img->dependencies))))) + /* Free cache based on timestamp. */ + EMACS_TIME t; + unsigned long old; + int delay, nimages = 0; + + for (i = 0; i < c->used; ++i) + if (c->images[i]) + nimages++; + + /* If the number of cached images has grown unusually large, + decrease the cache eviction delay (Bug#6230). */ + delay = XFASTINT (Vimage_cache_eviction_delay); + if (nimages > 40) + delay = max (1, 1600 * delay / (nimages*nimages)); + + EMACS_GET_TIME (t); + old = EMACS_SECS (t) - delay; + + for (i = 0; i < c->used; ++i) { - free_image (f, img); - ++nfreed; + struct image *img = c->images[i]; + if (img && img->timestamp < old) + { + free_image (f, img); + ++nfreed; + } } } @@ -8520,11 +8547,14 @@ Vx_bitmap_file_path = decode_env_path ((char *) 0, PATH_BITMAPS); DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay, - doc: /* Time after which cached images are removed from the cache. -When an image has not been displayed this many seconds, remove it -from the image cache. Value must be an integer or nil with nil -meaning don't clear the cache. */); - Vimage_cache_eviction_delay = make_number (30 * 60); + doc: /* Maximum time after which images are removed from the cache. +When an image has not been displayed this many seconds, Emacs +automatically removes it from the image cache. If the cache contains +a large number of images, the actual eviction time may be shorter. +The value can also be nil, meaning the cache is never cleared. + +The function `clear-image-cache' disregards this variable. */); + Vimage_cache_eviction_delay = make_number (300); } void
--- a/src/xdisp.c Fri May 21 09:31:45 2010 -0700 +++ b/src/xdisp.c Fri May 21 13:29:27 2010 -0400 @@ -12499,22 +12499,25 @@ if (windows_or_buffers_changed && !pause) goto retry; - /* Clear the face cache eventually. */ - if (consider_all_windows_p) - { - if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT) - { - clear_face_cache (0); - clear_face_cache_count = 0; - } -#ifdef HAVE_WINDOW_SYSTEM - if (clear_image_cache_count > CLEAR_IMAGE_CACHE_COUNT) - { - clear_image_caches (Qnil); - clear_image_cache_count = 0; - } + /* Clear the face and image caches. + + We used to do this only if consider_all_windows_p. But the cache + needs to be cleared if a timer creates images in the current + buffer (e.g. the test case in Bug#6230). */ + + if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT) + { + clear_face_cache (0); + clear_face_cache_count = 0; + } + +#ifdef HAVE_WINDOW_SYSTEM + if (clear_image_cache_count > CLEAR_IMAGE_CACHE_COUNT) + { + clear_image_caches (Qnil); + clear_image_cache_count = 0; + } #endif /* HAVE_WINDOW_SYSTEM */ - } end_of_redisplay: unbind_to (count, Qnil);