From 98fe5161c42a5ec64df3d0418f918a5ab8c909d6 Mon Sep 17 00:00:00 2001 From: Chong Yidong Date: Fri, 21 May 2010 13:29:27 -0400 Subject: 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. --- src/image.c | 70 +++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 20 deletions(-) (limited to 'src/image.c') diff --git a/src/image.c b/src/image.c index 030e06ad77..5d4f50ee85 100644 --- a/src/image.c +++ b/src/image.c @@ -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)) + { + /* 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 @@ 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 -- cgit v1.2.3 From 110683addccf829fa2b98fa279246f60a228d4fa Mon Sep 17 00:00:00 2001 From: Chong Yidong Date: Sat, 22 May 2010 12:48:01 -0400 Subject: Rename image-refresh to image-flush. * image.c (Fimage_flush): Rename from image-refresh. * image.el (image-refresh): Define as an alias for image-flush. * image-mode.el (image-toggle-display-image): Caller changed. * display.texi (Image Cache): Update documentation about image caching. --- doc/lispref/display.texi | 53 ++++++++++++++++++++++++++++-------------------- lisp/ChangeLog | 6 ++++++ lisp/image-mode.el | 4 ++-- lisp/image.el | 1 + src/ChangeLog | 4 ++++ src/image.c | 12 ++++++----- 6 files changed, 51 insertions(+), 29 deletions(-) (limited to 'src/image.c') diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 68631dcdef..622de2cd3c 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -4730,29 +4730,35 @@ cache, it can always be displayed, even if the value of efficiently. When Emacs displays an image, it searches the image cache for an existing image specification @code{equal} to the desired specification. If a match is found, the image is displayed from the -cache; otherwise, Emacs loads the image normally. - - Occasionally, you may need to tell Emacs to refresh the images -associated with a given image specification. For example, suppose you -display an image using a specification that contains a @code{:file} -property. The image is automatically cached, and subsequent displays -of that image, with the same image specification, will use the image -cache. If the image file changes in the meantime, Emacs would be -displaying the old version of the image. In such a situation, you can -``refresh'' the image by calling @code{image-refresh}. - - In Emacs' current implementation, each graphical terminal possesses -an image cache, which is shared by all the frames on that terminal +cache. Otherwise, Emacs loads the image normally. + +@defun image-flush spec &optional frame +This function removes the image with specification @var{spec} from the +image cache of frame @var{frame}. Image specifications are compared +using @code{equal}. If @var{frame} is @code{nil}, it defaults to the +selected frame. If @var{frame} is @code{t}, the image is flushed on +all existing frames. + +In Emacs' current implementation, each graphical terminal possesses an +image cache, which is shared by all the frames on that terminal (@pxref{Multiple Terminals}). Thus, refreshing an image in one frame also refreshes it in all other frames on the same terminal. - -@defun image-refresh spec &optional frame -This function refreshes any images with image specifications -@code{equal} to @var{spec} on frame @var{frame}. If @var{frame} is -@code{nil}, it defaults to the selected frame. If @var{frame} is -@code{t}, the refresh is applied to all existing frames. @end defun + One use for @code{image-flush} is to tell Emacs about a change in an +image file. If an image specification contains a @code{:file} +property, the image is cached based on the file's contents when the +image is first displayed. Even if the file subsequently changes, +Emacs continues displaying the old version of the image. Calling +@code{image-flush} flushes the image from the cache, forcing Emacs to +re-read the file the next time it needs to display that image. + + Another use for @code{image-flush} is for memory conservation. If +your Lisp program creates a large number of temporary images over a +period much shorter than @code{image-cache-eviction-delay} (see +below), you can opt to flush unused images yourself, instead of +waiting for Emacs to do it automatically. + @defun clear-image-cache &optional filter This function clears an image cache, removing all the images stored in it. If @var{filter} is omitted or @code{nil}, it clears the cache for @@ -4768,9 +4774,12 @@ period of time, Emacs removes it from the cache and frees the associated memory. @defvar image-cache-eviction-delay -This variable specifies the number of seconds an image can remain in the -cache without being displayed. When an image is not displayed for this -length of time, Emacs removes it from the image cache. +This variable specifies the number of seconds an image can remain in +the cache without being displayed. When an image is not displayed for +this length of time, Emacs removes it from the image cache. + +Under some circumstances, if the number of images in the cache grows +too large, the actual eviction delay may be shorter than this. If the value is @code{nil}, Emacs does not remove images from the cache except when you explicitly clear it. This mode can be useful for diff --git a/lisp/ChangeLog b/lisp/ChangeLog index e59c4a45c2..72f00e60ed 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,9 @@ +2010-05-22 Chong Yidong + + * image.el (image-refresh): Define as an alias for image-flush. + + * image-mode.el (image-toggle-display-image): Caller changed. + 2010-05-21 Juri Linkov * progmodes/grep.el (grep-read-files): Fix multi-pattern aliases. diff --git a/lisp/image-mode.el b/lisp/image-mode.el index dfc96bb4a1..f1323563d5 100644 --- a/lisp/image-mode.el +++ b/lisp/image-mode.el @@ -448,7 +448,7 @@ Remove text properties that display the image." (defvar archive-superior-buffer) (defvar tar-superior-buffer) -(declare-function image-refresh "image.c" (spec &optional frame)) +(declare-function image-flush "image.c" (spec &optional frame)) (defun image-toggle-display-image () "Show the image of the image file. @@ -477,7 +477,7 @@ was inserted." (inhibit-read-only t) (buffer-undo-list t) (modified (buffer-modified-p))) - (image-refresh image) + (image-flush image) (let ((buffer-file-truename nil)) ; avoid changing dir mtime by lock_file (add-text-properties (point-min) (point-max) props) (restore-buffer-modified-p modified)) diff --git a/lisp/image.el b/lisp/image.el index 67c1ad946b..b3a0f1a8a7 100644 --- a/lisp/image.el +++ b/lisp/image.el @@ -30,6 +30,7 @@ "Image support." :group 'multimedia) +(defalias 'image-refresh 'image-flush) (defconst image-type-header-regexps `(("\\`/[\t\n\r ]*\\*.*XPM.\\*/" . xpm) diff --git a/src/ChangeLog b/src/ChangeLog index f0613a5740..489505f3cf 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,7 @@ +2010-05-22 Chong Yidong + + * image.c (Fimage_flush): Rename from image-refresh. + 2010-05-21 Chong Yidong * xdisp.c (redisplay_internal): Clear caches even if redisplaying diff --git a/src/image.c b/src/image.c index 5d4f50ee85..b9620e1094 100644 --- a/src/image.c +++ b/src/image.c @@ -1689,11 +1689,13 @@ which is then usually a filename. */) } -DEFUN ("image-refresh", Fimage_refresh, Simage_refresh, +DEFUN ("image-flush", Fimage_flush, Simage_flush, 1, 2, 0, - doc: /* Refresh the image with specification SPEC on frame FRAME. -If SPEC specifies an image file, the displayed image is updated with -the current contents of that file. + doc: /* Fush the image with specification SPEC on frame FRAME. +This removes the image from the Emacs image cache. If SPEC specifies +an image file, the next redisplay of this image will read from the +current contents of that file. + FRAME nil or omitted means use the selected frame. FRAME t means refresh the image on all frames. */) (spec, frame) @@ -8526,7 +8528,7 @@ non-numeric, there is no explicit limit on the size of images. */); defsubr (&Sinit_image_library); defsubr (&Sclear_image_cache); - defsubr (&Simage_refresh); + defsubr (&Simage_flush); defsubr (&Simage_size); defsubr (&Simage_mask_p); defsubr (&Simage_metadata); -- cgit v1.2.3