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.
This commit is contained in:
Chong Yidong 2010-05-21 13:29:27 -04:00
parent 6a6dbaceca
commit 98fe5161c4
3 changed files with 76 additions and 34 deletions

View file

@ -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):

View file

@ -1582,29 +1582,56 @@ clear_image_cache (struct frame *f, Lisp_Object filter)
{
struct image_cache *c = FRAME_IMAGE_CACHE (f);
if (c && (!NILP (filter) || INTEGERP (Vimage_cache_eviction_delay)))
if (c)
{
EMACS_TIME t;
unsigned long old;
int i, nfreed;
EMACS_GET_TIME (t);
old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
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))
{
struct image *img = c->images[i];
if (img != NULL
&& (NILP (filter) ? img->timestamp < old
: (EQ (Qt, filter)
|| !NILP (Fmember (filter, img->dependencies)))))
/* Filter image cache. */
for (i = 0; i < c->used; ++i)
{
free_image (f, img);
++nfreed;
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))
{
/* 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)
{
struct image *img = c->images[i];
if (img && img->timestamp < old)
{
free_image (f, img);
++nfreed;
}
}
}
@ -8520,11 +8547,14 @@ A cross is always drawn on black & white displays. */);
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

View file

@ -12499,23 +12499,26 @@ redisplay_internal (preserve_echo_area)
if (windows_or_buffers_changed && !pause)
goto retry;
/* Clear the face cache eventually. */
if (consider_all_windows_p)
/* 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)
{
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 */
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);
RESUME_POLLING;