Несколько непонятностей по 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