From 6572976e06758d6faf5d2eebaf88fe0b92487f14 Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Sun, 12 May 2019 00:18:03 -0400 Subject: [PATCH] [core] chunkqueue perf: code reuse code reuse, simplification, and inlining remove excess calls to chunkqueue_remove_finished_chunks() (it may still be possible for there to be an empty chunk in chunkqueue if nothing were written to a temporary file (need to verify this), so preserve some calls to chunkqueue_remove_finished_chunks() for now) --- src/chunk.c | 135 ++++++++++++++++++------------------------------- src/connections-glue.c | 5 +- src/connections.c | 4 +- src/gw_backend.c | 2 - src/mod_webdav.c | 3 -- 5 files changed, 50 insertions(+), 99 deletions(-) diff --git a/src/chunk.c b/src/chunk.c index 73c9fd68..d2419990 100644 --- a/src/chunk.c +++ b/src/chunk.c @@ -208,55 +208,36 @@ void chunkqueue_chunk_pool_free(void) } static off_t chunk_remaining_length(const chunk *c) { - off_t len = 0; - switch (c->type) { - case MEM_CHUNK: - len = buffer_string_length(c->mem); - break; - case FILE_CHUNK: - len = c->file.length; - break; - default: - force_assert(c->type == MEM_CHUNK || c->type == FILE_CHUNK); - break; - } - force_assert(c->offset <= len); - return len - c->offset; + /* MEM_CHUNK or FILE_CHUNK */ + return (c->type == MEM_CHUNK + ? (off_t)buffer_string_length(c->mem) + : c->file.length) + - c->offset; +} + +static void chunkqueue_release_chunks(chunkqueue *cq) { + cq->last = NULL; + for (chunk *c; (c = cq->first); ) { + cq->first = c->next; + chunk_release(c); + } } void chunkqueue_free(chunkqueue *cq) { - chunk *c, *pc; - - if (NULL == cq) return; - - for (c = cq->first; c; ) { - pc = c; - c = c->next; - chunk_release(pc); - } - - free(cq); + if (NULL == cq) return; + chunkqueue_release_chunks(cq); + free(cq); } static void chunkqueue_prepend_chunk(chunkqueue *cq, chunk *c) { - c->next = cq->first; - cq->first = c; - - if (NULL == cq->last) { - cq->last = c; - } + if (NULL == (c->next = cq->first)) cq->last = c; + cq->first = c; } static void chunkqueue_append_chunk(chunkqueue *cq, chunk *c) { - c->next = NULL; - if (cq->last) { - cq->last->next = c; - } - cq->last = c; - - if (NULL == cq->first) { - cq->first = c; - } + c->next = NULL; + *(cq->last ? &cq->last->next : &cq->first) = c; + cq->last = c; } static chunk * chunkqueue_prepend_mem_chunk(chunkqueue *cq, size_t sz) { @@ -283,19 +264,10 @@ static chunk * chunkqueue_append_file_chunk(chunkqueue *cq, buffer *fn, off_t of } void chunkqueue_reset(chunkqueue *cq) { - chunk *cur = cq->first; - - cq->first = cq->last = NULL; - - while (NULL != cur) { - chunk *next = cur->next; - chunk_release(cur); - cur = next; - } - - cq->bytes_in = 0; - cq->bytes_out = 0; - cq->tempdir_idx = 0; + chunkqueue_release_chunks(cq); + cq->bytes_in = 0; + cq->bytes_out = 0; + cq->tempdir_idx = 0; } void chunkqueue_append_file_fd(chunkqueue *cq, buffer *fn, int fd, off_t offset, off_t len) { @@ -723,49 +695,38 @@ off_t chunkqueue_length(chunkqueue *cq) { } void chunkqueue_mark_written(chunkqueue *cq, off_t len) { - off_t written = len; - chunk *c; - force_assert(len >= 0); - - for (c = cq->first; NULL != c; c = cq->first) { - off_t c_len = chunk_remaining_length(c); - - if (0 == written && 0 != c_len) break; /* no more finished chunks */ - - if (written >= c_len) { /* chunk got finished */ - c->offset += c_len; - written -= c_len; - - cq->first = c->next; - if (c == cq->last) cq->last = NULL; - chunk_release(c); - } else { /* partial chunk */ - c->offset += written; - written = 0; - break; /* chunk not finished */ - } - } + cq->bytes_out += len; + + for (chunk *c; (c = cq->first); ) { + off_t c_len = chunk_remaining_length(c); + if (len >= c_len) { /* chunk got finished */ + len -= c_len; + cq->first = c->next; + chunk_release(c); + if (0 == len) break; + } + else { /* partial chunk */ + c->offset += len; + return; /* chunk not finished */ + } + } - force_assert(0 == written); - cq->bytes_out += len; + if (NULL == cq->first) + cq->last = NULL; + else + chunkqueue_remove_finished_chunks(cq); } void chunkqueue_remove_finished_chunks(chunkqueue *cq) { - chunk *c; - - for (c = cq->first; c; c = cq->first) { - if (0 != chunk_remaining_length(c)) break; /* not finished yet */ - - cq->first = c->next; - if (c == cq->last) cq->last = NULL; - chunk_release(c); - } + for (chunk *c; (c = cq->first) && 0 == chunk_remaining_length(c); ){ + if (NULL == (cq->first = c->next)) cq->last = NULL; + chunk_release(c); + } } static void chunkqueue_remove_empty_chunks(chunkqueue *cq) { chunk *c; chunkqueue_remove_finished_chunks(cq); - if (chunkqueue_is_empty(cq)) return; for (c = cq->first; c && c->next; c = c->next) { if (0 == chunk_remaining_length(c->next)) { diff --git a/src/connections-glue.c b/src/connections-glue.c index e1657966..d8c4a536 100644 --- a/src/connections-glue.c +++ b/src/connections-glue.c @@ -344,7 +344,6 @@ int connection_write_chunkqueue(server *srv, connection *con, chunkqueue *cq, of ret = con->network_write(srv, con, cq, max_bytes); if (ret >= 0) { - chunkqueue_remove_finished_chunks(cq); ret = chunkqueue_is_empty(cq) ? 0 : 1; } @@ -394,9 +393,7 @@ static int connection_write_100_continue(server *srv, connection *con) { return 0; /* error */ } - if (written == sizeof(http_100_continue)-1) { - chunkqueue_remove_finished_chunks(cq); - } else if (0 == written) { + if (0 == written) { /* skip sending 100 Continue if send would block */ chunkqueue_mark_written(cq, sizeof(http_100_continue)-1); con->is_writable = 0; diff --git a/src/connections.c b/src/connections.c index 7cc73007..6375e1fa 100644 --- a/src/connections.c +++ b/src/connections.c @@ -741,12 +741,10 @@ static void connection_read_header(server *srv, connection *con) { if (len > hlen) len = hlen; buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, len); - c->offset += len; - cq->bytes_out += len; if (0 == (hlen -= len)) break; } - chunkqueue_remove_finished_chunks(cq); + chunkqueue_mark_written(cq, con->header_len); /* skip past \r\n or \n after previous POST request when keep-alive */ if (con->request_count > 1) { diff --git a/src/gw_backend.c b/src/gw_backend.c index b7976ec5..2020111d 100644 --- a/src/gw_backend.c +++ b/src/gw_backend.c @@ -1831,8 +1831,6 @@ static handler_t gw_write_request(server *srv, gw_handler_ctx *hctx) { ret = srv->network_backend_write(srv, hctx->fd, hctx->wb, MAX_WRITE_LIMIT); - chunkqueue_remove_finished_chunks(hctx->wb); - if (ret < 0) { switch(errno) { case EPIPE: diff --git a/src/mod_webdav.c b/src/mod_webdav.c index 5ac16ca0..121e4033 100644 --- a/src/mod_webdav.c +++ b/src/mod_webdav.c @@ -3440,7 +3440,6 @@ webdav_parse_chunkqueue (connection * const con, weWant -= weHave; chunkqueue_mark_written(cq, weHave); - chunkqueue_remove_finished_chunks(cq); } if (XML_ERR_OK == err) { @@ -4105,7 +4104,6 @@ mod_webdav_write_cq_first_chunk (connection * const con, chunkqueue * const cq, if (wr > 0) { chunkqueue_mark_written(cq, wr); - chunkqueue_remove_finished_chunks(cq); } else if (wr < 0) http_status_set_error(con, (errno == ENOSPC) ? 507 : 403); @@ -4327,7 +4325,6 @@ mod_webdav_put_linkat_rename (connection * const con, } chunkqueue_mark_written(cq, c->file.length); - chunkqueue_remove_finished_chunks(cq); return 1; } -- 2.11.4.GIT