[cairo] mallocs in gstate_save

Baz brian.ewins at gmail.com
Wed Nov 14 03:54:53 PST 2007

Hi all,
Just looking at Stuart Parmenter's allocation dumps:
http://pavlovdotnet.wordpress.com/2007/11/13/allocation-data/ ...
there was some chat on irc about the mass of
_cairo_clip_intersect_path allocs, but I didn't see gstate
save/restore discussed - seems we have 5.9 meg of allocs in
gstate_save. I'm wondering if there's an easy win here.

In the 5-deep traces there are 323+330+389+918+1776 allocs in
cairo_create, and 174+378+977+1776+2789+8104+8689 calls to gstate_save
(not adding up the figures so you can see where they're coming from).
So unsurprisingly, save/restore happens multiple times on each
cairo_t. It seems likely that this is going to be several save/restore
pairs in sequence, rather than stack of save/restores, so we're
freeing allocations we could reuse.

So, my question is - would it be sensible in this case to just hang on
to the previous alloc (just reducing allocs rather than addressing the
fragmentation issue). Something like the code below;
_cairo_gstate_destroy would become tail-recursive to free this up

_cairo_gstate_save (cairo_gstate_t **gstate)
    cairo_gstate_t *top;

    /* a new member pointing at the previous allocation. better name?
preallocated? */
    if (*gstate->allocated) {
       top = *gstate->allocated;
       status = _cairo_gstate_init_copy (top, *gstate);
       if (status)
          return status;
    } else {
        top = _cairo_gstate_clone (*gstate);
        if (top == NULL)
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
        *gstate->allocated = top;
    top->next = *gstate;
    *gstate = top;


_cairo_gstate_restore (cairo_gstate_t **gstate)
    cairo_gstate_t *top;

    top = *gstate;
    if (top->next == NULL)
	return _cairo_error (CAIRO_STATUS_INVALID_RESTORE);

    *gstate = top->next;

    /* No need to destroy top; *gstate->allocated is still pointing to it */
    /* _cairo_gstate_destroy (top); */


More information about the cairo mailing list