From bb566ceafe3230d55923cb3043c3b231e4b9c0f9 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Mon, 19 Aug 2013 13:47:27 -0700 Subject: [PATCH] * image.c: Shrink memory needed for animation cache. (SIGNATURE_DIGESTSIZE): New constant. (struct animation_cache): Make 'signature' a fixed size array of bytes. (imagemagick_create_cache): Copy the signature. This saves several KB of memory that ImageMagick wastes per signature. Don't bother updating the update_time, as the caller does that now. (imagemagick_prune_animation_cache): Don't destroy the signature, as it's a fixed size struct member now. (imagemagick_get_animation_cache): Always destroy the signature, as it's now imagemagick_create_cache's responsibility to copy it. Avoid duplicate calls to strcmp and to imagemagick_create_cache, and use memcmp rather than strcmp. eassert that ImageMagick returns a signature of the specified length. --- src/ChangeLog | 16 ++++++++++++++++ src/image.c | 36 ++++++++++++++++++------------------ 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 2171f2b8748..d0bafd3914e 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,19 @@ +2013-08-19 Paul Eggert + + * image.c: Shrink memory needed for animation cache. + (SIGNATURE_DIGESTSIZE): New constant. + (struct animation_cache): Make 'signature' a fixed size array of bytes. + (imagemagick_create_cache): Copy the signature. This saves + several KB of memory that ImageMagick wastes per signature. + Don't bother updating the update_time, as the caller does that now. + (imagemagick_prune_animation_cache): Don't destroy the signature, as + it's a fixed size struct member now. + (imagemagick_get_animation_cache): Always destroy the signature, + as it's now imagemagick_create_cache's responsibility to copy it. + Avoid duplicate calls to strcmp and to imagemagick_create_cache, + and use memcmp rather than strcmp. + eassert that ImageMagick returns a signature of the specified length. + 2013-08-19 Lars Magne Ingebrigtsen * image.c (imagemagick_get_animation_cache): Don't segfault on diff --git a/src/image.c b/src/image.c index 7a6323ad332..4970d40af33 100644 --- a/src/image.c +++ b/src/image.c @@ -7876,13 +7876,17 @@ imagemagick_filename_hint (Lisp_Object spec, char hint_buffer[MaxTextExtent]) separate from the image cache, because the images may be scaled before display. */ +/* Size of ImageMagick image signatures, in bytes. It's SHA-256 as a + hex string, so it's 256 bits represented via 4 bits per byte. */ +enum { SIGNATURE_DIGESTSIZE = 256 / 4 }; + struct animation_cache { - char *signature; MagickWand *wand; int index; EMACS_TIME update_time; struct animation_cache *next; + char signature[SIGNATURE_DIGESTSIZE]; }; static struct animation_cache *animation_cache = NULL; @@ -7891,11 +7895,10 @@ static struct animation_cache * imagemagick_create_cache (char *signature) { struct animation_cache *cache = xmalloc (sizeof *cache); - cache->signature = signature; cache->wand = 0; cache->index = 0; cache->next = 0; - cache->update_time = current_emacs_time (); + memcpy (cache->signature, signature, SIGNATURE_DIGESTSIZE); return cache; } @@ -7914,7 +7917,6 @@ imagemagick_prune_animation_cache (void) pcache = &cache->next; else { - DestroyString (cache->signature); if (cache->wand) DestroyMagickWand (cache->wand); *pcache = cache->next; @@ -7928,24 +7930,22 @@ imagemagick_get_animation_cache (MagickWand *wand) { char *signature = MagickGetImageSignature (wand); struct animation_cache *cache; + struct animation_cache **pcache = &animation_cache; + eassert (strlen (signature) == SIGNATURE_DIGESTSIZE); imagemagick_prune_animation_cache (); - cache = animation_cache; - if (! cache) + while (1) { - animation_cache = imagemagick_create_cache (signature); - return animation_cache; - } - - while (strcmp (signature, cache->signature) && - cache->next) - cache = cache->next; - - if (strcmp (signature, cache->signature)) - { - cache->next = imagemagick_create_cache (signature); - return cache->next; + cache = *pcache; + if (! cache) + { + *pcache = cache = imagemagick_create_cache (signature); + break; + } + if (memcmp (signature, cache->signature, SIGNATURE_DIGESTSIZE) == 0) + break; + pcache = &cache->next; } DestroyString (signature); -- 2.39.2