[syslog-ng] Per-thread scratch buffers

Balazs Scheidler bazsi at balabit.hu
Mon Oct 31 22:02:03 CET 2011


On Mon, 2011-10-31 at 21:38 +0100, Balazs Scheidler wrote:
> On Mon, 2011-10-31 at 10:16 +0100, Gergely Nagy wrote:
> > Balazs Scheidler <bazsi at balabit.hu> writes:
> > 
> > > The alternative idea I was playing with was to create a new API for
> > > managing per-thread scratch buffers that could be reused even between
> > > multiple independent portions of syslog-ng.
> > >
> > > The way it would work:
> > >   - scratch buffers are a numbered array of GString buffers, allocated
> > >     for _each_ thread.
> > 
> > Any reason we want per-thread scratch buffers? Apart from not needing to
> > use a lock in this case..
> 
> that's the point, and to keep GString instances around.
> 
> > 
> > As a first step in implementing this, I had something like the following
> > in mind:
> > 
> > static GTrashStack *scratch_buffers;
> > 
> > GString *scratch_buffer_acquite (void)
> 
> a typo in the function name.
> 
> > {
> >   GString *s;
> > 
> >   s = g_trash_stack_pop (scratch_buffers);
> >   if (!s)
> >     s = g_string_new (NULL);
> >   else
> >     g_string_set_size (s, 0);
> >   return s;
> > }
> 
> are you sure that once you get your GString instance back from
> GTrashStack, it'll be a valid GString?
> 
> GTrashStack seems to corrupt the first pointer of each data block pushed
> to it (which is the "str" pointer in this case).
> 
> > 
> > void scratch_buffer_release (GString *s)
> > {
> >   g_trash_stack_push (s);
> > }
> > 
> > void scratch_buffers_reset (void)
> > {
> >   GString *s;
> > 
> >   while ((s = g_trash_stack_pop (scratch_buffers)) != NULL)
> >     g_string_free (s, TRUE);
> > }
> 
> I wouldn't want to free the GString instances, but reuse them. This is
> the other point: to avoid having to allocate new GString instances all
> the time.
> 
> The implementation I had in mind was:
>   - dynamically sized array of GString instances (per-thread)
>   - a stack pointer that contains the index within the array where we
>     are at. Items below the pointer are used, above are not.
>   - acquire: if there are unused items in the array, return it and
>     increase the pointer. if there are no unused items, allocate new and
>     store it in the array.
>   - release: if the item to be freed is the one handed out last,
>     decrement the pointer, else do nothing.
>   - reset: reset the pointer to 0.
> 
> This way: 
>   - the number of GString instances depend on their usage.
>   - GStrings are only allocated rarely, if the parallel number of
>     GString buffers increase for some reason.
>   - no need for locking as scratch buffers are per-thread
> 
> Of course it only shows its potential if all the similar cases already
> in the code are converted to scratch buffers (log_template_format,
> template functions, value-pairs, etc).

After I've posted this I noticed the implementation in follow-up
patches. Those comments came after this, so read them too :)

-- 
Bazsi




More information about the syslog-ng mailing list