[gegl] buffer: in gegl-tile-alloc, keep a spare empty block
- From: Ell <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] buffer: in gegl-tile-alloc, keep a spare empty block
- Date: Sun, 26 Apr 2020 11:24:35 +0000 (UTC)
commit 54d1ef723ecded5e2c7987f43d0278c4f216ed29
Author: Ell <ell_se yahoo com>
Date: Sun Apr 26 14:20:56 2020 +0300
buffer: in gegl-tile-alloc, keep a spare empty block
In gegl-tile-alloc, when all tiles in a block are freed, keep a
single empty block around at any given time as a spare, and reuse
the block when a new one is required. This avoids frequent block
allocation and freeing when a single (or few) tiles on the edge of
a block are repeadtedly allocated/freed.
gegl/buffer/gegl-tile-alloc.c | 202 ++++++++++++++++++++++++++++--------------
gegl/buffer/gegl-tile-alloc.h | 3 +
gegl/gegl-init.c | 3 +
3 files changed, 143 insertions(+), 65 deletions(-)
---
diff --git a/gegl/buffer/gegl-tile-alloc.c b/gegl/buffer/gegl-tile-alloc.c
index c7cf44ec3..e1a0d4a9b 100644
--- a/gegl/buffer/gegl-tile-alloc.c
+++ b/gegl/buffer/gegl-tile-alloc.c
@@ -81,6 +81,7 @@ static GeglTileBlock * gegl_tile_block_new (GeglTileBlock * volat
gsize size);
static void gegl_tile_block_free (GeglTileBlock *block,
GeglTileBlock **head_block);
+static void gegl_tile_block_free_mem (GeglTileBlock *block);
static inline gpointer gegl_tile_buffer_to_data (GeglTileBuffer *buffer);
static inline GeglTileBuffer * gegl_tile_buffer_from_data (gpointer data);
@@ -93,6 +94,7 @@ static gpointer gegl_tile_alloc_fallback (gsize
static const gint gegl_tile_divisors[] = {1, 3, 5};
static GeglTileBlock *gegl_tile_blocks[G_N_ELEMENTS (gegl_tile_divisors)]
[GEGL_TILE_MAX_SIZE_LOG2];
+static GeglTileBlock *gegl_tile_empty_block;
static gint gegl_tile_n_blocks;
static gint gegl_tile_max_n_blocks;
@@ -138,66 +140,99 @@ static GeglTileBlock *
gegl_tile_block_new (GeglTileBlock * volatile *block_ptr,
gsize size)
{
- GeglTileBlock *block;
- GeglTileBuffer *buffer;
- GeglTileBuffer **next_buffer;
- gsize block_size;
- gsize buffer_size;
- gsize n_buffers;
- gint n_blocks;
- gint i;
+ GeglTileBlock *block;
+ gsize block_size;
+ gsize buffer_size;
+ gsize n_buffers;
+ gboolean init_block = TRUE;
buffer_size = GEGL_TILE_BUFFER_DATA_OFFSET + GEGL_ALIGN (size);
- block_size = floor (gegl_buffer_config ()->tile_cache_size *
- GEGL_TILE_BLOCK_SIZE_RATIO);
- block_size -= block_size % buffer_size;
+ do
+ {
+ block = gegl_tile_empty_block;
+ }
+ while (block &&
+ ! g_atomic_pointer_compare_and_exchange (&gegl_tile_empty_block,
+ block, NULL));
- n_buffers = block_size / buffer_size;
- n_buffers = MIN (n_buffers, GEGL_TILE_BLOCK_MAX_BUFFERS);
+ if (block && block->size - GEGL_TILE_BLOCK_BUFFER_OFFSET < buffer_size)
+ {
+ gegl_tile_block_free_mem (block);
- if (n_buffers <= 1)
- return NULL;
+ block = NULL;
+ }
- block_size = n_buffers * buffer_size;
+ if (block)
+ {
+ block_size = block->size;
- block = gegl_try_malloc (GEGL_TILE_BLOCK_BUFFER_OFFSET + block_size);
+ n_buffers = (block_size - GEGL_TILE_BLOCK_BUFFER_OFFSET) / buffer_size;
- if (! block)
- return NULL;
+ if (block->block_ptr == block_ptr)
+ init_block = FALSE;
+ }
+ else
+ {
+ gint n_blocks;
- block->block_ptr = block_ptr;
- block->size = GEGL_TILE_BLOCK_BUFFER_OFFSET + block_size;
+ block_size = floor (gegl_buffer_config ()->tile_cache_size *
+ GEGL_TILE_BLOCK_SIZE_RATIO);
+ block_size -= block_size % buffer_size;
- block->head = (GeglTileBuffer *) ((guint8 *) block +
- GEGL_TILE_BLOCK_BUFFER_OFFSET);
- block->n_allocated = 0;
+ n_buffers = block_size / buffer_size;
+ n_buffers = MIN (n_buffers, GEGL_TILE_BLOCK_MAX_BUFFERS);
- block->prev = NULL;
- block->next = NULL;
+ if (n_buffers <= 1)
+ return NULL;
- buffer = block->head;
+ block_size = GEGL_TILE_BLOCK_BUFFER_OFFSET + n_buffers * buffer_size;
- for (i = n_buffers; i; i--)
- {
- buffer->block = block;
+ block = gegl_try_malloc (block_size);
- next_buffer = gegl_tile_buffer_to_data (buffer);
+ if (! block)
+ return NULL;
- if (i > 1)
- buffer = (GeglTileBuffer *) ((guint8 *) buffer + buffer_size);
- else
- buffer = NULL;
+ n_blocks = g_atomic_int_add (&gegl_tile_n_blocks, +1) + 1;
+
+ if (n_blocks % GEGL_TILE_BLOCKS_PER_TRIM == 0)
+ gegl_tile_max_n_blocks = MAX (gegl_tile_max_n_blocks, n_blocks);
- *next_buffer = buffer;
+ g_atomic_pointer_add (&gegl_tile_alloc_total, +block_size);
}
- n_blocks = g_atomic_int_add (&gegl_tile_n_blocks, +1) + 1;
+ if (init_block)
+ {
+ GeglTileBuffer *buffer;
+ GeglTileBuffer **next_buffer;
+ gint i;
+
+ block->block_ptr = block_ptr;
+ block->size = block_size;
- if (n_blocks % GEGL_TILE_BLOCKS_PER_TRIM == 0)
- gegl_tile_max_n_blocks = MAX (gegl_tile_max_n_blocks, n_blocks);
+ block->head = (GeglTileBuffer *) ((guint8 *) block +
+ GEGL_TILE_BLOCK_BUFFER_OFFSET);
+ block->n_allocated = 0;
- g_atomic_pointer_add (&gegl_tile_alloc_total, +block->size);
+ block->prev = NULL;
+ block->next = NULL;
+
+ buffer = block->head;
+
+ for (i = n_buffers; i; i--)
+ {
+ buffer->block = block;
+
+ next_buffer = gegl_tile_buffer_to_data (buffer);
+
+ if (i > 1)
+ buffer = (GeglTileBuffer *) ((guint8 *) buffer + buffer_size);
+ else
+ buffer = NULL;
+
+ *next_buffer = buffer;
+ }
+ }
return block;
}
@@ -206,9 +241,6 @@ static void
gegl_tile_block_free (GeglTileBlock *block,
GeglTileBlock **head_block)
{
- guintptr block_size = block->size;
- gint n_blocks;
-
if (block->prev)
block->prev->next = block->next;
else
@@ -217,6 +249,27 @@ gegl_tile_block_free (GeglTileBlock *block,
if (block->next)
block->next->prev = block->prev;
+ if (! gegl_tile_empty_block)
+ {
+ block->prev = NULL;
+ block->next = NULL;
+
+ if (g_atomic_pointer_compare_and_exchange (&gegl_tile_empty_block,
+ NULL, block))
+ {
+ return;
+ }
+ }
+
+ gegl_tile_block_free_mem (block);
+}
+
+static void
+gegl_tile_block_free_mem (GeglTileBlock *block)
+{
+ guintptr block_size = block->size;
+ gint n_blocks;
+
gegl_free (block);
n_blocks = g_atomic_int_add (&gegl_tile_n_blocks, -1) - 1;
@@ -276,6 +329,28 @@ gegl_tile_alloc_enabled (void)
/* public functions */
+void
+gegl_tile_alloc_init (void)
+{
+}
+
+void
+gegl_tile_alloc_cleanup (void)
+{
+ GeglTileBlock *block;
+
+ do
+ {
+ block = gegl_tile_empty_block;
+ }
+ while (block &&
+ ! g_atomic_pointer_compare_and_exchange (&gegl_tile_empty_block,
+ block, NULL));
+
+ if (block)
+ gegl_tile_block_free_mem (block);
+}
+
gpointer
gegl_tile_alloc (gsize size)
{
@@ -364,10 +439,11 @@ gegl_tile_alloc0 (gsize size)
void
gegl_tile_free (gpointer ptr)
{
- GeglTileBlock * volatile *block_ptr;
- GeglTileBlock *block;
- GeglTileBlock *head_block;
- GeglTileBuffer *buffer;
+ GeglTileBlock * volatile *block_ptr;
+ GeglTileBlock *block;
+ GeglTileBlock *head_block;
+ GeglTileBuffer *buffer;
+ GeglTileBuffer **next_buffer;
if (! ptr)
return;
@@ -395,30 +471,26 @@ gegl_tile_free (gpointer ptr)
block->n_allocated--;
- if (block->n_allocated == 0)
- {
- gegl_tile_block_free (block, &head_block);
- }
- else
- {
- GeglTileBuffer **next_buffer = gegl_tile_buffer_to_data (buffer);
-
- *next_buffer = block->head;
+ next_buffer = gegl_tile_buffer_to_data (buffer);
- if (! block->head)
- {
- block->prev = NULL;
- block->next = head_block;
+ *next_buffer = block->head;
- if (head_block)
- head_block->prev = block;
+ if (! block->head)
+ {
+ block->prev = NULL;
+ block->next = head_block;
- head_block = block;
- }
+ if (head_block)
+ head_block->prev = block;
- block->head = buffer;
+ head_block = block;
}
+ block->head = buffer;
+
+ if (block->n_allocated == 0)
+ gegl_tile_block_free (block, &head_block);
+
g_atomic_pointer_set (block_ptr, head_block);
}
diff --git a/gegl/buffer/gegl-tile-alloc.h b/gegl/buffer/gegl-tile-alloc.h
index 78cb02c08..6fcfe18e2 100644
--- a/gegl/buffer/gegl-tile-alloc.h
+++ b/gegl/buffer/gegl-tile-alloc.h
@@ -20,6 +20,9 @@
#define __GEGL_TILE_ALLOC_H__
+void gegl_tile_alloc_init (void);
+void gegl_tile_alloc_cleanup (void);
+
/* the buffer returned by gegl_tile_alloc() and gegl_tile_alloc0() is
* guaranteed to have room for two `int`s in front of the buffer.
*/
diff --git a/gegl/gegl-init.c b/gegl/gegl-init.c
index 739349939..6482f952c 100644
--- a/gegl/gegl-init.c
+++ b/gegl/gegl-init.c
@@ -75,6 +75,7 @@ guint gegl_debug_flags = 0;
#include "buffer/gegl-buffer-iterator-private.h"
#include "buffer/gegl-buffer-swap-private.h"
#include "buffer/gegl-compression.h"
+#include "buffer/gegl-tile-alloc.h"
#include "buffer/gegl-tile-backend-ram.h"
#include "buffer/gegl-tile-backend-file.h"
#include "gegl-config.h"
@@ -409,6 +410,7 @@ gegl_exit (void)
gegl_random_cleanup ();
gegl_parallel_cleanup ();
gegl_buffer_swap_cleanup ();
+ gegl_tile_alloc_cleanup ();
gegl_cl_cleanup ();
gegl_temp_buffer_free ();
@@ -599,6 +601,7 @@ gegl_post_parse_hook (GOptionContext *context,
GEGL_INSTRUMENT_START();
+ gegl_tile_alloc_init ();
gegl_buffer_swap_init ();
gegl_parallel_init ();
gegl_compression_init ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]