MEDIUM: buffers: make b_xfer() automatically swap buffers when possible
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.
diff --git a/include/common/buf.h b/include/common/buf.h
index e72de91..6d46111 100644
--- a/include/common/buf.h
+++ b/include/common/buf.h
@@ -517,7 +517,9 @@
/* 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 @@
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)