[PATCH 2 of 2] Event pipe: reduced number of file buffers used

Maxim Dounin mdounin at mdounin.ru
Fri Oct 21 09:21:19 UTC 2011


# HG changeset patch
# User Maxim Dounin <mdounin at mdounin.ru>
# Date 1319187535 -14400
# Node ID 761bf79b5415190ed29a89b4197f6b7ca33ea2e0
# Parent  268d6673848018d7390de41b73414546da6f6463
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).

diff --git a/src/event/ngx_event_pipe.c b/src/event/ngx_event_pipe.c
--- 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) {
 
diff --git a/src/event/ngx_event_pipe.h b/src/event/ngx_event_pipe.h
--- 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;
 



More information about the nginx-devel mailing list