Skip to content

Commit

Permalink
INTERNAL: Reduce add_iov() work for TCP connections
Browse files Browse the repository at this point in the history
Back in 2006 memcached's frontend was optimized for primarily UDP traffic. The
extra fiddling for every subsection of a response has persisted since then,
where most users are TCP. Shortening this function has a large effect on
performance (6%+)
  • Loading branch information
ing-eoking authored and jhpark816 committed Feb 22, 2024
1 parent 59c88e5 commit 94ba0d8
Showing 1 changed file with 43 additions and 26 deletions.
69 changes: 43 additions & 26 deletions memcached.c
Original file line number Diff line number Diff line change
Expand Up @@ -1206,54 +1206,71 @@ static int ensure_iov_space(conn *c)
* connection.
*
* Returns 0 on success, -1 on out-of-memory.
* Note: This is a hot path for at least ASCII protocol. While there is
* redundant code in splitting TCP/UDP handling, any reduction in steps has a
* large impact for TCP connections.
*/

static int add_iov(conn *c, const void *buf, int len)
{
assert(c != NULL);
struct msghdr *m;
int leftover;
bool limit_to_mtu;

do {
m = &c->msglist[c->msgused - 1];
if (IS_UDP(c->transport)) {
do {
m = &c->msglist[c->msgused - 1];

/*
* Limit UDP packets, and the first payloads of TCP replies, to
* UDP_MAX_PAYLOAD_SIZE bytes.
*/
limit_to_mtu = IS_UDP(c->transport) || (1 == c->msgused);
/*
* Limit UDP packets to UDP_MAX_PAYLOAD_SIZE bytes.
*/

/* We may need to start a new msghdr if this one is full. */
if (m->msg_iovlen == IOV_MAX ||
(c->msgbytes >= UDP_MAX_PAYLOAD_SIZE)) {
add_msghdr(c);
m = &c->msglist[c->msgused - 1];
}

/* We may need to start a new msghdr if this one is full. */
if (m->msg_iovlen == IOV_MAX ||
(limit_to_mtu && c->msgbytes >= UDP_MAX_PAYLOAD_SIZE)) {
if (ensure_iov_space(c) != 0)
return -1;

/* If the fragment is too big to fit in the datagram, split it up */
if (len + c->msgbytes > UDP_MAX_PAYLOAD_SIZE) {
leftover = len + c->msgbytes - UDP_MAX_PAYLOAD_SIZE;
len -= leftover;
} else {
leftover = 0;
}

m = &c->msglist[c->msgused - 1];
m->msg_iov[m->msg_iovlen].iov_base = (void *)buf;
m->msg_iov[m->msg_iovlen].iov_len = len;

c->msgbytes += len;
c->iovused++;
m->msg_iovlen++;

buf = ((char *)buf) + len;
len = leftover;
} while (leftover > 0);
} else {
/* Optimized path for TCP connections */
m = &c->msglist[c->msgused - 1];
if (m->msg_iovlen == IOV_MAX) {
add_msghdr(c);
m = &c->msglist[c->msgused - 1];
}

if (ensure_iov_space(c) != 0)
return -1;

/* If the fragment is too big to fit in the datagram, split it up */
if (limit_to_mtu && len + c->msgbytes > UDP_MAX_PAYLOAD_SIZE) {
leftover = len + c->msgbytes - UDP_MAX_PAYLOAD_SIZE;
len -= leftover;
} else {
leftover = 0;
}

m = &c->msglist[c->msgused - 1];
m->msg_iov[m->msg_iovlen].iov_base = (void *)buf;
m->msg_iov[m->msg_iovlen].iov_len = len;

c->msgbytes += len;
c->iovused++;
m->msg_iovlen++;

buf = ((char *)buf) + len;
len = leftover;
} while (leftover > 0);

}
return 0;
}

Expand Down

0 comments on commit 94ba0d8

Please sign in to comment.