summaryrefslogtreecommitdiff
path: root/buckets
diff options
context:
space:
mode:
authorbrianp <brianp@13f79535-47bb-0310-9956-ffa450edef68>2002-09-21 16:30:43 +0000
committerbrianp <brianp@13f79535-47bb-0310-9956-ffa450edef68>2002-09-21 16:30:43 +0000
commit52786d184c70a42e3a21514a13fd0f4125090585 (patch)
tree831ba8d5969d0701ade39cd5cb852b520aae9499 /buckets
parent72c7dbee65e08713695acfa1f7c809fba4824008 (diff)
downloadlibapr-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.c73
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,