From 3ba802e99524797571e69ba57b6a30a12b031b72 Mon Sep 17 00:00:00 2001 From: rubidium Date: Mon, 23 Feb 2009 17:54:02 +0000 Subject: [PATCH] (svn r15556) -Change: don't temporary malloc+free when encoding sprites, just reuse the same piece of allocated memory for each encoding. --- src/blitter/8bpp_optimized.cpp | 8 +++-- src/core/alloc_type.hpp | 55 +++++++++++++++++++++++++++++++ src/spritecache.cpp | 15 +-------- src/spriteloader/spriteloader.hpp | 11 +++---- 4 files changed, 66 insertions(+), 23 deletions(-) diff --git a/src/blitter/8bpp_optimized.cpp b/src/blitter/8bpp_optimized.cpp index 350715dc6b..62fae35c88 100644 --- a/src/blitter/8bpp_optimized.cpp +++ b/src/blitter/8bpp_optimized.cpp @@ -113,7 +113,12 @@ Sprite *Blitter_8bppOptimized::Encode(SpriteLoader::Sprite *sprite, Blitter::All /* We have no idea how much memory we really need, so just guess something */ memory *= 5; - SpriteData *temp_dst = (SpriteData *)MallocT(memory); + + /* Don't allocate memory each time, but just keep some + * memory around as this function is called quite often + * and the memory usage is quite low. */ + static ReusableBuffer temp_buffer; + SpriteData *temp_dst = (SpriteData *)temp_buffer.Allocate(memory); byte *dst = temp_dst->data; /* Make the sprites per zoom-level */ @@ -195,7 +200,6 @@ Sprite *Blitter_8bppOptimized::Encode(SpriteLoader::Sprite *sprite, Blitter::All dest_sprite->x_offs = sprite->x_offs; dest_sprite->y_offs = sprite->y_offs; memcpy(dest_sprite->data, temp_dst, size); - free(temp_dst); return dest_sprite; } diff --git a/src/core/alloc_type.hpp b/src/core/alloc_type.hpp index a2bda93e4c..887ba72370 100644 --- a/src/core/alloc_type.hpp +++ b/src/core/alloc_type.hpp @@ -70,6 +70,61 @@ struct SmallStackSafeStackAlloc { } }; +/** + * A reusable buffer that can be used for places that temporary allocate + * a bit of memory and do that very often, or for places where static + * memory is allocated that might need to be reallocated sometimes. + * + * Every time Allocate or ZeroAllocate is called previous results of both + * functions will become invalid. + */ +template +class ReusableBuffer { +private: + T *buffer; ///< The real data buffer + size_t count; ///< Number of T elements in the buffer + +public: + /** Create a new buffer */ + ReusableBuffer() : buffer(NULL), count(0) {} + /** Clear the buffer */ + ~ReusableBuffer() { free(this->buffer); } + + /** + * Get buffer of at least count times T. + * @note the buffer might be bigger + * @note calling this function invalidates any previous buffers given + * @param count the minimum buffer size + * @return the buffer + */ + T *Allocate(size_t count) + { + if (this->count < count) { + free(this->buffer); + this->buffer = MallocT(count); + } + return this->buffer; + } + + /** + * Get buffer of at least count times T with zeroed memory. + * @note the buffer might be bigger + * @note calling this function invalidates any previous buffers given + * @param count the minimum buffer size + * @return the buffer + */ + T *ZeroAllocate(size_t count) + { + if (this->count < count) { + free(this->buffer); + this->buffer = CallocT(count); + } else { + memset(this->buffer, 0, sizeof(T) * count); + } + return this->buffer; + } +}; + /** * Base class that provides memory initialization on dynamically created objects. * All allocated memory will be zeroed. diff --git a/src/spritecache.cpp b/src/spritecache.cpp index c5fa7f0370..0e7bb95501 100644 --- a/src/spritecache.cpp +++ b/src/spritecache.cpp @@ -560,17 +560,4 @@ void GfxInitSpriteMem() _compact_cache_counter = 0; } -void SpriteLoader::Sprite::AllocateData(size_t size) -{ - if (Sprite::size < size) { - Sprite::size = size; - Sprite::mem = ReallocT(Sprite::mem, Sprite::size); - } - - memset(Sprite::mem, 0, sizeof(SpriteLoader::CommonPixel) * size); - - this->data = Sprite::mem; - -} -/* static */ SpriteLoader::CommonPixel *SpriteLoader::Sprite::mem = NULL; -/* static */ size_t SpriteLoader::Sprite::size = 0; +/* static */ ReusableBuffer SpriteLoader::Sprite::buffer; diff --git a/src/spriteloader/spriteloader.hpp b/src/spriteloader/spriteloader.hpp index 9b431fb4fe..762831ae4e 100644 --- a/src/spriteloader/spriteloader.hpp +++ b/src/spriteloader/spriteloader.hpp @@ -5,6 +5,8 @@ #ifndef SPRITELOADER_HPP #define SPRITELOADER_HPP +#include "../core/alloc_type.hpp" + class SpriteLoader { public: struct CommonPixel { @@ -22,9 +24,6 @@ public: * This to prevent thousands of malloc + frees just to load a sprite. */ struct Sprite { - Sprite() : data(NULL) {} - ~Sprite() { assert(this->data == NULL || this->data == Sprite::mem); } - uint16 height; ///< Height of the sprite uint16 width; ///< Width of the sprite int16 x_offs; ///< The x-offset of where the sprite will be drawn @@ -35,12 +34,10 @@ public: * Allocate the sprite data of this sprite. * @param size the minimum size of the data field. */ - void AllocateData(size_t size); + void AllocateData(size_t size) { this->data = Sprite::buffer.ZeroAllocate(size); } private: /** Allocated memory to pass sprite data around */ - static SpriteLoader::CommonPixel *mem; - /** Size (in items) of the above memory. */ - static size_t size; + static ReusableBuffer buffer; }; /**