mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-02-14 15:40:39 +01:00
[cairo] Keep a small stash of cairo contexts
A cairo context is meant to be extremely cheap to create such that it can be used in transient expose events. Thus these are allocated reasonably frequently and show up malloc profiles.
This commit is contained in:
parent
f08fe5b550
commit
7d8a0a1cdd
1 changed files with 49 additions and 2 deletions
51
src/cairo.c
51
src/cairo.c
|
|
@ -117,6 +117,53 @@ _cairo_set_error (cairo_t *cr, cairo_status_t status)
|
|||
status = _cairo_error (status);
|
||||
}
|
||||
|
||||
#if HAS_ATOMIC_OPS
|
||||
/* We keep a small stash of contexts to reduce malloc pressure */
|
||||
#define CAIRO_STASH_SIZE 4
|
||||
static struct {
|
||||
cairo_t pool[CAIRO_STASH_SIZE];
|
||||
int occupied;
|
||||
} _context_stash;
|
||||
|
||||
static cairo_t *
|
||||
_context_get (void)
|
||||
{
|
||||
int avail, old, new;
|
||||
|
||||
do {
|
||||
old = _context_stash.occupied;
|
||||
avail = ffs (~old) - 1;
|
||||
if (avail >= CAIRO_STASH_SIZE)
|
||||
return malloc (sizeof (cairo_t));
|
||||
|
||||
new = old | (1 << avail);
|
||||
} while (_cairo_atomic_int_cmpxchg (&_context_stash.occupied, old, new) != old);
|
||||
|
||||
return &_context_stash.pool[avail];
|
||||
}
|
||||
|
||||
static void
|
||||
_context_put (cairo_t *cr)
|
||||
{
|
||||
int old, new, avail;
|
||||
|
||||
if (cr < &_context_stash.pool[0] ||
|
||||
cr >= &_context_stash.pool[CAIRO_STASH_SIZE])
|
||||
{
|
||||
return free (cr);
|
||||
}
|
||||
|
||||
avail = ~(1 << (cr - &_context_stash.pool[0]));
|
||||
do {
|
||||
old = _context_stash.occupied;
|
||||
new = old & avail;
|
||||
} while (_cairo_atomic_int_cmpxchg (&_context_stash.occupied, old, new) != old);
|
||||
}
|
||||
#else
|
||||
#define _context_get() malloc (sizeof (cairo_t))
|
||||
#define _context_put(cr) free (cr)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* cairo_create:
|
||||
* @target: target surface for the context
|
||||
|
|
@ -150,7 +197,7 @@ cairo_create (cairo_surface_t *target)
|
|||
if (target && target->status == CAIRO_STATUS_NO_MEMORY)
|
||||
return (cairo_t *) &_cairo_nil;
|
||||
|
||||
cr = malloc (sizeof (cairo_t));
|
||||
cr = _context_get ();
|
||||
if (unlikely (cr == NULL)) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_t *) &_cairo_nil;
|
||||
|
|
@ -248,7 +295,7 @@ cairo_destroy (cairo_t *cr)
|
|||
|
||||
_cairo_user_data_array_fini (&cr->user_data);
|
||||
|
||||
free (cr);
|
||||
_context_put (cr);
|
||||
}
|
||||
slim_hidden_def (cairo_destroy);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue