From 01f90c58eff005e9fb5c91157aaa41255782af44 Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Fri, 2 Oct 2020 03:19:37 -0400 Subject: [PATCH] [core] walk queue in connection_write_chunkqueue() walk chunkqueue up to first FILE_CHUNK (if present) This may incur memory load misses for pointer chasing, but effectively preloads part of the chunkqueue, something which used to be a side effect of a previous (less efficient) version of chunkqueue_length() which walked the entire chunkqueue (on each and every call). The loads here make a measurable difference in performance in underlying call to con->network_write() --- src/connections.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/connections.c b/src/connections.c index a142c6ba..2892e000 100644 --- a/src/connections.c +++ b/src/connections.c @@ -282,8 +282,10 @@ connection_write_throttle (connection * const con, off_t max_bytes) static int -connection_write_chunkqueue (connection * const con, chunkqueue * const cq, off_t max_bytes) +connection_write_chunkqueue (connection * const con, chunkqueue * const restrict cq, off_t max_bytes) { + /*assert(!chunkqueue_is_empty(cq));*//* checked by callers */ + con->write_request_ts = log_epoch_secs; max_bytes = connection_write_throttle(con, max_bytes); @@ -293,24 +295,33 @@ connection_write_chunkqueue (connection * const con, chunkqueue * const cq, off_ int ret; #ifdef TCP_CORK - /* Linux: put a cork into socket as we want to combine write() calls - * but only if we really have multiple chunks including non-MEM_CHUNK, - * and only if TCP socket - */ int corked = 0; - if (cq->first && cq->first->next) { - const int sa_family = sock_addr_get_family(&con->srv_socket->addr); - if (sa_family == AF_INET || sa_family == AF_INET6) { - chunk *c = cq->first; - while (c->type == MEM_CHUNK && NULL != (c = c->next)) ; - if (NULL != c) { + #endif + + /* walk chunkqueue up to first FILE_CHUNK (if present) + * This may incur memory load misses for pointer chasing, but effectively + * preloads part of the chunkqueue, something which used to be a side effect + * of a previous (less efficient) version of chunkqueue_length() which + * walked the entire chunkqueue (on each and every call). The loads here + * make a measurable difference in performance in underlying call to + * con->network_write() */ + if (cq->first->next) { + const chunk *c = cq->first; + while (c->type == MEM_CHUNK && NULL != (c = c->next)) ; + #ifdef TCP_CORK + /* Linux: put a cork into socket as we want to combine write() calls + * but only if we really have multiple chunks including non-MEM_CHUNK + * (or if multiple chunks and TLS), and only if TCP socket */ + if (NULL != c || con->is_ssl_sock) { + const int sa_family = sock_addr_get_family(&con->srv_socket->addr); + if (sa_family == AF_INET || sa_family == AF_INET6) { corked = 1; (void)setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked)); } } + #endif } - #endif ret = con->network_write(con, cq, max_bytes); if (ret >= 0) {