aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxim Dounin <mdounin@mdounin.ru>2011-10-31 09:54:55 +0000
committerMaxim Dounin <mdounin@mdounin.ru>2011-10-31 09:54:55 +0000
commit0d59500343d3cea70b89eb57e45be86da69c0f8d (patch)
tree313078e6fa7e0d2a64b9ef7b810e3fd537c4a692 /src
parent59205ce10909ca0b50fbc70f4bf98e539ce176d5 (diff)
downloadnginx-0d59500343d3cea70b89eb57e45be86da69c0f8d.tar.gz
nginx-0d59500343d3cea70b89eb57e45be86da69c0f8d.zip
Event pipe: reduced number of file buffers used.
If possible we now just extend already present file buffer in p->out chain instead of keeping ngx_buf_t for each buffer we've flushed to disk. This saves about 120 bytes of memory per buffer flushed to disk, and resolves high CPU usage observed in edge cases (due to coalescing these buffers on send).
Diffstat (limited to 'src')
-rw-r--r--src/event/ngx_event_pipe.c75
-rw-r--r--src/event/ngx_event_pipe.h2
2 files changed, 55 insertions, 22 deletions
diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c
index a770485d4..c389f2eba 100644
--- a/src/event/ngx_event_pipe.c
+++ b/src/event/ngx_event_pipe.c
@@ -680,10 +680,10 @@ ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p)
static ngx_int_t
ngx_event_pipe_write_chain_to_temp_file(ngx_event_pipe_t *p)
{
- ssize_t size, bsize;
+ ssize_t size, bsize, n;
ngx_buf_t *b;
ngx_uint_t prev_last_shadow;
- ngx_chain_t *cl, *tl, *next, *out, **ll, **last_free, fl;
+ ngx_chain_t *cl, *tl, *next, *out, **ll, **last_out, **last_free, fl;
if (p->buf_to_file) {
fl.buf = p->buf_to_file;
@@ -748,42 +748,77 @@ ngx_event_pipe_write_chain_to_temp_file(ngx_event_pipe_t *p)
p->last_in = &p->in;
}
- if (ngx_write_chain_to_temp_file(p->temp_file, out) == NGX_ERROR) {
- return NGX_ABORT;
- }
+ n = ngx_write_chain_to_temp_file(p->temp_file, out);
- for (last_free = &p->free_raw_bufs;
- *last_free != NULL;
- last_free = &(*last_free)->next)
- {
- /* void */
+ if (n == NGX_ERROR) {
+ return NGX_ABORT;
}
if (p->buf_to_file) {
p->temp_file->offset = p->buf_to_file->last - p->buf_to_file->pos;
+ n -= p->buf_to_file->last - p->buf_to_file->pos;
p->buf_to_file = NULL;
out = out->next;
}
- for (cl = out; cl; cl = next) {
- next = cl->next;
- cl->next = NULL;
+ if (n > 0) {
+ /* update previous buffer or add new buffer */
+
+ if (p->out) {
+ for (cl = p->out; cl->next; cl = cl->next) { /* void */ }
+
+ b = cl->buf;
+
+ if (b->file_last == p->temp_file->offset) {
+ p->temp_file->offset += n;
+ b->file_last = p->temp_file->offset;
+ goto free;
+ }
+
+ last_out = &cl->next;
+
+ } else {
+ last_out = &p->out;
+ }
+
+ cl = ngx_chain_get_free_buf(p->pool, &p->free);
+ if (cl == NULL) {
+ return NGX_ABORT;
+ }
b = cl->buf;
+
+ ngx_memzero(b, sizeof(ngx_buf_t));
+
+ b->tag = p->tag;
+
b->file = &p->temp_file->file;
b->file_pos = p->temp_file->offset;
- p->temp_file->offset += b->last - b->pos;
+ p->temp_file->offset += n;
b->file_last = p->temp_file->offset;
b->in_file = 1;
b->temp_file = 1;
- if (p->out) {
- *p->last_out = cl;
- } else {
- p->out = cl;
- }
- p->last_out = &cl->next;
+ *last_out = cl;
+ }
+
+free:
+
+ for (last_free = &p->free_raw_bufs;
+ *last_free != NULL;
+ last_free = &(*last_free)->next)
+ {
+ /* void */
+ }
+
+ for (cl = out; cl; cl = next) {
+ next = cl->next;
+
+ cl->next = p->free;
+ p->free = cl;
+
+ b = cl->buf;
if (b->last_shadow) {
diff --git a/src/event/ngx_event_pipe.h b/src/event/ngx_event_pipe.h
index 26334673c..8f55431e8 100644
--- a/src/event/ngx_event_pipe.h
+++ b/src/event/ngx_event_pipe.h
@@ -30,8 +30,6 @@ struct ngx_event_pipe_s {
ngx_chain_t **last_in;
ngx_chain_t *out;
- ngx_chain_t **last_out;
-
ngx_chain_t *free;
ngx_chain_t *busy;