From a7de9501f6d0f3a574c5246b81d78aa749b64e67 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sun, 8 Apr 2007 23:24:50 -0400 Subject: [PATCH] [cairo-skiplist] Group levels two-by-two in freelists Most memory allocators allocate in multiples of twice the size of a pointer. So there is no point in keeping freelists for both even and odd levels. We now round odd levels up to the next even level for freelist computations. This reduces the number of node mallocations. --- src/cairo-skiplist-private.h | 10 +++++++++- src/cairo-skiplist.c | 21 ++++++++++++++------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/cairo-skiplist-private.h b/src/cairo-skiplist-private.h index 2ad40341c..4be1aa07d 100644 --- a/src/cairo-skiplist-private.h +++ b/src/cairo-skiplist-private.h @@ -34,6 +34,14 @@ #define MAX_LEVEL 31 +/* Returns the index of the free-list to use for a node at level 'level' */ +#define FREELIST_FOR_LEVEL(level) (((level) - 1) / 2) + +/* Returns the maximum level that uses the same free-list as 'level' does */ +#define FREELIST_MAX_LEVEL_FOR(level) (((level) + 1) & ~1) + +#define MAX_FREELIST_LEVEL (FREELIST_FOR_LEVEL (MAX_LEVEL - 1) + 1) + /* * Skip list element. In order to use the skip list, the caller must * generate a structure for list elements that has as its final member @@ -58,7 +66,7 @@ typedef struct _skip_list { size_t elt_size; size_t data_size; skip_elt_t *chains[MAX_LEVEL]; - skip_elt_t *freelists[MAX_LEVEL]; + skip_elt_t *freelists[MAX_FREELIST_LEVEL]; int max_level; } cairo_skip_list_t; diff --git a/src/cairo-skiplist.c b/src/cairo-skiplist.c index c8a30184e..52d846527 100644 --- a/src/cairo-skiplist.c +++ b/src/cairo-skiplist.c @@ -232,6 +232,9 @@ _cairo_skip_list_init (cairo_skip_list_t *list, for (i = 0; i < MAX_LEVEL; i++) { list->chains[i] = NULL; + } + + for (i = 0; i < MAX_FREELIST_LEVEL; i++) { list->freelists[i] = NULL; } @@ -247,7 +250,7 @@ _cairo_skip_list_fini (cairo_skip_list_t *list) while ((elt = list->chains[0])) { _cairo_skip_list_delete_given (list, elt); } - for (i=0; ifreelists[i]; while (elt) { skip_elt_t *nextfree = elt->prev; @@ -282,19 +285,23 @@ random_level (void) static void * alloc_node_for_level (cairo_skip_list_t *list, unsigned level) { - if (list->freelists[level-1]) { - skip_elt_t *elt = list->freelists[level-1]; - list->freelists[level-1] = elt->prev; + int freelist_level = FREELIST_FOR_LEVEL (level); + if (list->freelists[freelist_level]) { + skip_elt_t *elt = list->freelists[freelist_level]; + list->freelists[freelist_level] = elt->prev; return ELT_DATA(elt); } - return malloc (list->elt_size + (level-1) * sizeof (skip_elt_t *)); + return malloc (list->elt_size + + (FREELIST_MAX_LEVEL_FOR (level) - 1) * sizeof (skip_elt_t *)); } static void free_elt (cairo_skip_list_t *list, skip_elt_t *elt) { - elt->prev = list->freelists[elt->prev_index]; - list->freelists[elt->prev_index] = elt; + int level = elt->prev_index + 1; + int freelist_level = FREELIST_FOR_LEVEL (level); + elt->prev = list->freelists[freelist_level]; + list->freelists[freelist_level] = elt; } /*