diff options
author | brianp <brianp@13f79535-47bb-0310-9956-ffa450edef68> | 2002-09-21 16:30:43 +0000 |
---|---|---|
committer | brianp <brianp@13f79535-47bb-0310-9956-ffa450edef68> | 2002-09-21 16:30:43 +0000 |
commit | 52786d184c70a42e3a21514a13fd0f4125090585 (patch) | |
tree | 831ba8d5969d0701ade39cd5cb852b520aae9499 /buckets | |
parent | 72c7dbee65e08713695acfa1f7c809fba4824008 (diff) | |
download | libapr-util-52786d184c70a42e3a21514a13fd0f4125090585.tar.gz |
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().
git-svn-id: http://svn.apache.org/repos/asf/apr/apr-util/trunk@58758 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'buckets')
-rw-r--r-- | buckets/apr_brigade.c | 73 |
1 files changed, 11 insertions, 62 deletions
diff --git a/buckets/apr_brigade.c b/buckets/apr_brigade.c index ea070afc..682f81f8 100644 --- a/buckets/apr_brigade.c +++ b/buckets/apr_brigade.c @@ -456,80 +456,29 @@ APU_DECLARE(apr_status_t) apr_brigade_puts(apr_bucket_brigade *bb, 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, |