]> git.kaiwu.me - nginx.git/commitdiff
Event pipe: reduced number of file buffers used.
authorMaxim Dounin <mdounin@mdounin.ru>
Mon, 31 Oct 2011 09:54:55 +0000 (09:54 +0000)
committerMaxim Dounin <mdounin@mdounin.ru>
Mon, 31 Oct 2011 09:54:55 +0000 (09:54 +0000)
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).

src/event/ngx_event_pipe.c
src/event/ngx_event_pipe.h

index a770485d46c4b31c61a3647e9b9e518053649232..c389f2ebacaf8c5e8c4324130becf54ffec8d941 100644 (file)
@@ -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) {
 
index 26334673c4f85703a08ec727a59c20e488179ee7..8f55431e8c59c4a00d5100204d4bed9b645e2efa 100644 (file)
@@ -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;