On Tuesday 26 February 2013, Christophe JAILLET wrote: > My understanding is that: > - apr_brigade_[putc|puts|write...] try to reuse last bucket if > possible, avoiding memory allocation > - if needed (not enough space available, not allowed to write > in the last bucket), it creates a heap bucket of 8k or more (or > transient one if flushed is requested)) > - and then call APR_BRIGADE_INSERT_TAIL > > So the 2 constructions are quite similar. > > > Doing so would: > + try to use already allocated memory, so reduce memory > footprint + avoid memory fragmentation by avoiding small buckets + > reduce code length, so improve readability (IMO) > - BUT, would allocate, when needed, 8k of memory at a time > instead of using the memory already available in a pool, so > increasing memory footprint...
I think some rules for chosing between the two are: 1) If it is not performance relevant (e.g. mod_status, mod_info, ...), use apr_brigade_put* because it makes the code simpler/smaller. IMHO even the apr_r* functions are ok in this case. 2) if the string is large (let's say > 1K), use APR_BRIGADE_INSERT_TAIL to avoid copying. 3) if it is done many times in a loop, use apr_brigade_put*. The many calls will fill up the 8k buffer and the separate bucket structs that would be created by many APR_BRIGADE_INSERT_TAIL() calls would use quite some memory, too (64 byte each on 32bit archs, more on 64bit archs). 4) if it is likely that the next data inserted into the brigade will not be done with apr_brigade_[putc|puts|write...] but by appending a bucket, use APR_BRIGADE_INSERT_TAIL() even if the inserted string is small. If none of the above, use your best judgement ;-) The mod_include case you cited matches 1+3 (because it was in the printenv function). Therefore using apr_brigade_put* was ok. Cheers, Stefan
