Несколько непонятностей по nginx

Igor Sysoev is at rambler-co.ru
Tue Apr 24 19:50:09 MSD 2007


On Tue, Apr 24, 2007 at 06:38:51PM +0400, Александр Ворона wrote:

> Igor Sysoev пишет:
> 
> >0.5.18.2 откатить, 0.5.18.3 накатить.
> >
> Чистое ядро 64bit, nginx 0.5.19 + патч 0.5.18.3, limit_rate выключен.
> Нужный эффект неблокируемости достигнут, но наблюдаю родившийся 
> негативный. Однопотоковая закачка идёт в скорость диска - >50Мбайт/сек. 
> Закачка в 2 и больше потоков через 1 воркер с диска приводит к падению 
> суммарной скорости отдачи местами и меньше 10Мбайт/сек. Запустив 2 
> воркера и 2 закачки, убедившись через lsof -p каждого воркера, что идёт 
> по 1 закачке на воркер - получил желаемую суммарную скорость отдачи 
> >50Мбайт.
> 
> Пересобрал nginx с ngx_linux_sendfile_limit = 512 * 1024;
> 28Мбайт/сек в 2 потока с 1 воркера, утилизация диска 100%
> ~60 Мбайт 2 потока с 2-х воркеров, утилизация диска 100%
> ~65Мб 1 поток, утилизация диска 100%
> 
> lighttpd рядом с aio-sendfile показывает до 40мбайт на 2-х закачках с 
> диска, но скорость падает до ещё меньшего значения чем у nginx - 
> 6-7Мбайт/сек суммарно, утилизация диска 15% :). При убивании одной из 
> закачек вторая оживает до 50Мбайт в сек, при возобновлении 2-й закачки 
> о5 всё возвращается на 7Мбайт суммарно.
> 
> i386 ядро с патчем на sendfile(не в 128000,а в текущий размер буфера 
> сокета), nginx 0.5.19 + патч 0.5.18.3, отдача 5G файла
> Один поток - ~47Мбайт, утилизация диска 60-80% по iostat
> 2 потока 1 воркер - суммарная 20-25Мбайт, утилизация диска 90% по iostat
> 
> lighttpd sendfile
> Один поток - ~50Мбайт, утилизация диска 99-100% по iostat
> 2 потока суммарная 30-40Мбайт, утилизация диска 99-100% по iostat
> 
> Можно в nginx сделать размер равным текущему размеру буфера сокета, 
> вроде того, как я присылал патч и спрашивал почему он не работает :) ?
> Мне кажется, это положительно скажется на производительности. Хотя 
> лишний системный вызов перед каждым sendfile ...
> 
> Пытаюсь разшевелить lkml'щиков http://lkml.org/lkml/2007/4/23/289, но 
> особо много не добился. Проскочила разве что идея про новый системный 
> вызов splice(2.6.17+)

Прилагаемый патч делает директиву sendfile_limit, которой можно
выставлять требуемый лимит на уровнях http, server, location.

Кстати, а на каких ядрах это стало наблюдаться ?


-- 
Игорь Сысоев
http://sysoev.ru
-------------- next part --------------
Index: src/http/ngx_http_core_module.c
===================================================================
--- src/http/ngx_http_core_module.c	(revision 502)
+++ src/http/ngx_http_core_module.c	(working copy)
@@ -295,6 +295,17 @@
       offsetof(ngx_http_core_loc_conf_t, sendfile),
       NULL },
 
+#if (NGX_LINUX)
+
+    { ngx_string("sendfile_limit"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_size_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_core_loc_conf_t, sendfile_limit),
+      NULL },
+
+#endif
+
     { ngx_string("tcp_nopush"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
       ngx_conf_set_flag_slot,
@@ -2191,6 +2202,9 @@
     lcf->internal = NGX_CONF_UNSET;
     lcf->client_body_in_file_only = NGX_CONF_UNSET;
     lcf->sendfile = NGX_CONF_UNSET;
+#if (NGX_LINUX)
+    lcf->sendfile_limit = NGX_CONF_UNSET_SIZE;
+#endif
     lcf->tcp_nopush = NGX_CONF_UNSET;
     lcf->tcp_nodelay = NGX_CONF_UNSET;
     lcf->send_timeout = NGX_CONF_UNSET_MSEC;
@@ -2359,6 +2373,9 @@
     ngx_conf_merge_value(conf->client_body_in_file_only,
                               prev->client_body_in_file_only, 0);
     ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0);
+#if (NGX_LINUX)
+    ngx_conf_merge_size_value(conf->sendfile_limit, prev->sendfile_limit, 0);
+#endif
     ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0);
     ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1);
 
Index: src/http/ngx_http_core_module.h
===================================================================
--- src/http/ngx_http_core_module.h	(revision 502)
+++ src/http/ngx_http_core_module.h	(working copy)
@@ -245,6 +245,9 @@
     size_t        send_lowat;              /* send_lowat */
     size_t        postpone_output;         /* postpone_output */
     size_t        limit_rate;              /* limit_rate */
+#if (NGX_LINUX)
+    size_t        sendfile_limit;          /* sendfile_limit */
+#endif
 
     ngx_msec_t    client_body_timeout;     /* client_body_timeout */
     ngx_msec_t    send_timeout;            /* send_timeout */
Index: src/http/ngx_http_write_filter_module.c
===================================================================
--- src/http/ngx_http_write_filter_module.c	(revision 502)
+++ src/http/ngx_http_write_filter_module.c	(working copy)
@@ -47,7 +47,7 @@
 ngx_int_t
 ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
 {
-    off_t                      size, sent, to_send;
+    off_t                      size, sent, limit;
     ngx_uint_t                 last, flush;
     ngx_chain_t               *cl, *ln, **ll, *chain;
     ngx_connection_t          *c;
@@ -210,28 +210,35 @@
     }
 
     if (r->limit_rate) {
-        to_send = r->limit_rate * (ngx_time() - r->start_sec + 1) - c->sent;
+        limit = r->limit_rate * (ngx_time() - r->start_sec + 1) - c->sent;
 
-        if (to_send <= 0) {
+        if (limit <= 0) {
             c->write->delayed = 1;
             ngx_add_timer(c->write,
-                          (ngx_msec_t) (- to_send * 1000 / r->limit_rate + 1));
+                          (ngx_msec_t) (- limit * 1000 / r->limit_rate + 1));
 
             c->buffered |= NGX_HTTP_WRITE_BUFFERED;
 
             return NGX_AGAIN;
         }
 
+#if (NGX_LINUX)
+
+    } else if (clcf->sendfile_limit) {
+        limit = clcf->sendfile_limit;
+
+#endif
+
     } else {
-        to_send = 0;
+        limit = 0;
     }
 
     sent = c->sent;
 
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
-                   "http write filter to send %O", to_send);
+                   "http write filter to send %O", limit);
 
-    chain = c->send_chain(c, r->out, to_send);
+    chain = c->send_chain(c, r->out, limit);
 
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
                    "http write filter %p", chain);
@@ -241,12 +248,21 @@
         return NGX_ERROR;
     }
 
-    if (to_send) {
+    if (r->limit_rate) {
         sent = c->sent - sent;
         c->write->delayed = 1;
         ngx_add_timer(c->write, (ngx_msec_t) (sent * 1000 / r->limit_rate + 1));
     }
 
+#if (NGX_LINUX)
+
+      else if (c->write->ready && clcf->sendfile_limit) {
+        c->write->delayed = 1;
+        ngx_add_timer(c->write, 1);
+    }
+
+#endif
+
     for (cl = r->out; cl && cl != chain; /* void */) {
         ln = cl;
         cl = cl->next;


More information about the nginx-ru mailing list