]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: buffers: make b_xfer() automatically swap buffers when possible
authorWilly Tarreau <w@1wt.eu>
Fri, 20 Jul 2018 16:58:51 +0000 (18:58 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 20 Jul 2018 17:21:43 +0000 (19:21 +0200)
Whenever it's possible to avoid a copy, b_xfer() will simply swap the
buffer's heads without touching the data. This has brought the performance
back from 140 kH/s to 202 kH/s on the test case.

include/common/buf.h

index e72de911aba79eca936ceac663c30dbc92acffc2..6d461111250fa52c39c11375c30b99180d441a7b 100644 (file)
@@ -517,7 +517,9 @@ static inline size_t b_putblk(struct buffer *b, const char *blk, size_t len)
 /* b_xfer() : transfers at most <count> bytes from buffer <src> to buffer <dst>
  * and returns the number of bytes copied. The bytes are removed from <src> and
  * added to <dst>. The caller is responsible for ensuring that <count> is not
- * larger than b_room(dst).
+ * larger than b_room(dst). Whenever possible (if the destination is empty and
+ * at least as much as the source was requested), the buffers are simply
+ * swapped instead of copied.
  */
 static inline size_t b_xfer(struct buffer *dst, struct buffer *src, size_t count)
 {
@@ -533,6 +535,13 @@ static inline size_t b_xfer(struct buffer *dst, struct buffer *src, size_t count
 
        if (ret > count)
                ret = count;
+       else if (!b_data(dst)) {
+               /* zero copy is possible by just swapping buffers */
+               struct buffer tmp = *dst;
+               *dst = *src;
+               *src = tmp;
+               goto leave;
+       }
 
        block1 = b_contig_data(src, 0);
        if (block1 > ret)