]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: htx: make htx_add_data() never defragment the buffer
authorWilly Tarreau <w@1wt.eu>
Tue, 28 May 2019 08:58:50 +0000 (10:58 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 28 May 2019 12:48:59 +0000 (14:48 +0200)
Now instead of trying to fit 100% of the input data into the output
buffer at the risk of defragmenting it, we put what fits into it only
and return the amount of bytes transferred. In a test, compared to the
previous commit, it increases the cached data rate from 44 Gbps to
55 Gbps and saves a lot in case of large buffers : with a 1 MB buffer,
uncached transfers jumped from 700 Mbps to 30 Gbps.

src/htx.c

index 32e23d115ff7d9a68c9f1ee6150d299477a4ad79..9281ebac61c467814bcb0e48252f3b65c0d9c1c9 100644 (file)
--- a/src/htx.c
+++ b/src/htx.c
@@ -763,13 +763,69 @@ struct htx_blk *htx_add_endof(struct htx *htx, enum htx_blk_type type)
  */
 size_t htx_add_data(struct htx *htx, const struct ist data)
 {
-       struct htx_blk *blk;
+       struct htx_blk *blk, *tailblk, *headblk, *frtblk;
+       struct ist v;
+       int32_t room;
+       int32_t len = data.len;
+
+       if (!htx->used)
+               goto add_new_block;
+
+       /* Not enough space to store data */
+       if (len > htx_free_data_space(htx))
+               len = htx_free_data_space(htx);
 
-       blk = htx_add_data_atonce(htx, data);
-       if (blk)
-               return data.len;
+       if (!len)
+               return 0;
+
+       /* get the tail and head block */
+       tailblk = htx_get_tail_blk(htx);
+       headblk = htx_get_head_blk(htx);
+       if (tailblk == NULL || headblk == NULL)
+               goto add_new_block;
+
+       /* Don't try to append data if the last inserted block is not of the
+        * same type */
+       if (htx_get_blk_type(tailblk) != HTX_BLK_DATA)
+               goto add_new_block;
+
+       /*
+        * Same type and enough space: append data
+        */
+       frtblk = htx_get_blk(htx, htx->front);
+       if (tailblk->addr >= headblk->addr) {
+               if (htx->tail != htx->front)
+                       goto add_new_block;
+               room = sizeof(htx->blocks[0]) * htx_pos_to_idx(htx, htx->tail) - (frtblk->addr + htx_get_blksz(frtblk));
+       }
        else
+               room = headblk->addr - (tailblk->addr + htx_get_blksz(tailblk));
+
+       if (room < len)
+               len = room;
+
+  append_data:
+       /* get the value of the tail block */
+       /* FIXME: check v.len + len < 256MB */
+       v = htx_get_blk_value(htx, tailblk);
+
+       /* Append data and update the block itself */
+       memcpy(v.ptr + v.len, data.ptr, len);
+       htx_set_blk_value_len(tailblk, v.len + len);
+
+       /* Update HTTP message */
+       htx->data += len;
+       return len;
+
+  add_new_block:
+       /* FIXME: check tlr.len (< 256MB) */
+       blk = htx_add_blk(htx, HTX_BLK_DATA, len);
+       if (!blk)
                return 0;
+
+       blk->info += len;
+       memcpy(htx_get_blk_ptr(htx, blk), data.ptr, len);
+       return len;
 }
 
 /* Adds an HTX block of type TLR in <htx>. It returns the new block on