mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-06 09:18:11 +02:00
[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.
This commit is contained in:
parent
9da86e4a38
commit
a7de9501f6
2 changed files with 23 additions and 8 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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; i<MAX_LEVEL; i++) {
|
||||
for (i=0; i<MAX_FREELIST_LEVEL; i++) {
|
||||
elt = list->freelists[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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue