brianp 2002/09/21 09:30:43
Modified: buckets apr_brigade.c
Log:
Simpler, less optimized code for apr_brigade_puts()
The loop-unrolled code wasn't helping enough anyway,
because the httpd calls this function many times per
response to output short strings. I think we need
an alternate API that can amortize the function call
overhead and the heap bucket condition checking
across multiple string writes...quite possibly
apr_brigade_writev().
Revision Changes Path
1.49 +11 -62 apr-util/buckets/apr_brigade.c
Index: apr_brigade.c
===================================================================
RCS file: /home/cvs/apr-util/buckets/apr_brigade.c,v
retrieving revision 1.48
retrieving revision 1.49
diff -u -r1.48 -r1.49
--- apr_brigade.c 2 Jul 2002 18:20:57 -0000 1.48
+++ apr_brigade.c 21 Sep 2002 16:30:43 -0000 1.49
@@ -456,80 +456,29 @@
apr_brigade_flush flush, void
*ctx,
const char *str)
{
+ apr_size_t len = strlen(str);
apr_bucket *bkt = APR_BRIGADE_LAST(bb);
if (!APR_BRIGADE_EMPTY(bb) && APR_BUCKET_IS_HEAP(bkt)) {
- /* If there is some space available in a heap bucket
- * at the end of the brigade, start copying the string
+ /* If there is enough space available in a heap bucket
+ * at the end of the brigade, copy the string directly
+ * into the heap bucket
*/
apr_bucket_heap *h = bkt->data;
- char *buf = h->base + bkt->start + bkt->length;
apr_size_t bytes_avail = h->alloc_len - bkt->length;
- const char *saved_start = str;
- /* Optimization:
- * The loop that follows is an unrolled version of the original:
- * while (bytes_avail && *str) {
- * *buf++ = *str++;
- * bytes_avail--;
- * }
- * With that original loop, apr_brigade_puts() was showing
- * up as a surprisingly expensive function in httpd performance
- * profiling (it gets called a *lot*). This new loop reduces
- * the overhead from two conditional branch ops per character
- * to 1+1/8. The result is a 30% reduction in the cost of
- * apr_brigade_puts() in typical usage within the httpd.
- */
- while (bytes_avail >= 8) {
- /* Copy the next 8 characters (or fewer if we hit end of string)
*/
- if (!*str) {
- break;
- }
- *buf++ = *str++;
- if (!*str) {
- break;
- }
- *buf++ = *str++;
- if (!*str) {
- break;
- }
- *buf++ = *str++;
- if (!*str) {
- break;
- }
- *buf++ = *str++;
- if (!*str) {
- break;
- }
- *buf++ = *str++;
- if (!*str) {
- break;
- }
- *buf++ = *str++;
- if (!*str) {
- break;
- }
- *buf++ = *str++;
- if (!*str) {
- break;
- }
- *buf++ = *str++;
- bytes_avail -= 8;
- }
- bkt->length += (str - saved_start);
-
- /* If we had enough free space in the bucket to copy
- * the entire string, we're done
- */
- if (!*str) {
+ if (bytes_avail >= len) {
+ char *buf = h->base + bkt->start + bkt->length;
+ memcpy(buf, str, len);
+ bkt->length += len;
return APR_SUCCESS;
}
}
- /* If the string has not been copied completely to the brigade,
- * delegate the remaining work to apr_brigade_write(), which
+ /* If the string could not be copied into an existing heap
+ * bucket, delegate the work to apr_brigade_write(), which
* knows how to grow the brigade
*/
- return apr_brigade_write(bb, flush, ctx, str, strlen(str));
+ return apr_brigade_write(bb, flush, ctx, str, len);
}
APU_DECLARE_NONSTD(apr_status_t) apr_brigade_putstrs(apr_bucket_brigade *b,