MEDIUM: mux-h1: avoid a double copy on the Tx path whenever possible

In order to properly deal with unaligned contents, the output data are
currently copied into a temporary buffer, to be copied into the mux's
output buffer at the end. The new buffer API allows several buffers to
share the same data area, so we're using this here to make the temporary
buffer point to the same area as the output buffer when that one is
empty. This is enough to avoid the copy at the end, only pointers and
lengths have to be adjusted. In addition the output buffer's head is
advanced by the HTX header size so that the remaining copy is aligned.

By doing this we improve the large object performance by an extra 10%,
which is 64% above the 1.9-dev9 state. It's worth noting that there are
no more calls to __memcpy_sse2_unaligned() now.

Since this code deals with various block types, it appears difficult to
adjust it to be smart enough to even avoid the first copy. However a
distinct approach could consist in trying to detect a single blocked
HTX and jump to dedicated code in this case.
This commit is contained in:
Willy Tarreau 2018-12-05 11:19:27 +01:00
parent 78f548f49e
commit c5efa33021

View File

@ -1326,6 +1326,15 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun
tmp = get_trash_chunk();
/* pre-align the output buffer like the HTX in case it's empty. In this
* case since it's aligned we don't need to use the temporary trash.
*/
if (!b_data(&h1c->obuf)) {
h1c->obuf.head = sizeof(struct htx);
tmp->area = h1c->obuf.area + h1c->obuf.head;
}
tmp->size = b_room(&h1c->obuf);
blk = htx_get_head_blk(chn_htx);
@ -1472,7 +1481,13 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun
}
copy:
b_putblk(&h1c->obuf, tmp->area, tmp->data);
/* when the output buffer is empty, tmp shares the same area so that we
* only have to update pointers and lengths.
*/
if (tmp->area == h1c->obuf.area)
h1c->obuf.data = tmp->data;
else
b_putblk(&h1c->obuf, tmp->area, tmp->data);
if (!buf_room_for_htx_data(&h1c->obuf))
h1c->flags |= H1C_F_OUT_FULL;