changeset 4233:aae172db7ac8

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).
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 31 Oct 2011 09:54:55 +0000
parents 487ab473f393
children d5462eab1440
files src/event/ngx_event_pipe.c src/event/ngx_event_pipe.h
diffstat 2 files changed, 59 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- 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_e
 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,10 +748,63 @@ ngx_event_pipe_write_chain_to_temp_file(
         p->last_in = &p->in;
     }
 
-    if (ngx_write_chain_to_temp_file(p->temp_file, out) == NGX_ERROR) {
+    n = ngx_write_chain_to_temp_file(p->temp_file, out);
+
+    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;
+    }
+
+    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 += n;
+        b->file_last = p->temp_file->offset;
+
+        b->in_file = 1;
+        b->temp_file = 1;
+
+        *last_out = cl;
+    }
+
+free:
+
     for (last_free = &p->free_raw_bufs;
          *last_free != NULL;
          last_free = &(*last_free)->next)
@@ -759,31 +812,13 @@ ngx_event_pipe_write_chain_to_temp_file(
         /* void */
     }
 
-    if (p->buf_to_file) {
-        p->temp_file->offset = 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;
+
+        cl->next = p->free;
+        p->free = cl;
 
         b = cl->buf;
-        b->file = &p->temp_file->file;
-        b->file_pos = p->temp_file->offset;
-        p->temp_file->offset += b->last - b->pos;
-        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;
 
         if (b->last_shadow) {
 
--- 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;