SPDY: split big data frames
Yury Kirpichev
ykirpichev at gmail.com
Mon Jun 24 15:04:52 UTC 2013
Hi,
It is limitation of current nginx spdy implementation that whole data chain
is sent by single spdy data frame.
Below are changes where I tried to change this behavior and use 32kb data
frames at most in order to send outgoing spdy data.
Any comments are welcome.
# HG changeset patch
# User ykirpichev at gmail.com
# Date 1372085474 -14400
# Branch spdy_split_big_frame_default
# Node ID c8660bcdd8d3fb2ef12fa1edc1d0f39b771de51e
# Parent 982678c5c270f93a0c21ab6eb23cb123c0dc3df0
SPDY: split big frames
diff -r 982678c5c270 -r c8660bcdd8d3 src/core/ngx_buf.h
--- a/src/core/ngx_buf.h Wed Jun 12 00:41:24 2013 +0900
+++ b/src/core/ngx_buf.h Mon Jun 24 18:51:14 2013 +0400
@@ -158,5 +158,8 @@
void ngx_chain_update_chains(ngx_pool_t *p, ngx_chain_t **free,
ngx_chain_t **busy, ngx_chain_t **out, ngx_buf_tag_t tag);
+ ngx_int_t
+ngx_split_buf_in_chain(ngx_pool_t *pool, ngx_chain_t **chain,
+ ngx_chain_t *in, off_t buf_size);
#endif /* _NGX_BUF_H_INCLUDED_ */
diff -r 982678c5c270 -r c8660bcdd8d3 src/core/ngx_output_chain.c
--- a/src/core/ngx_output_chain.c Wed Jun 12 00:41:24 2013 +0900
+++ b/src/core/ngx_output_chain.c Mon Jun 24 18:51:14 2013 +0400
@@ -672,3 +672,59 @@
return NGX_AGAIN;
}
+
+
+ ngx_int_t
+ngx_split_buf_in_chain(ngx_pool_t *pool, ngx_chain_t **chain,
+ ngx_chain_t *in, off_t buf_size)
+{
+ ngx_chain_t *cl, **il;
+ ngx_buf_t *b, *buf;
+
+#if 0
+ if (!in->buf->in_file) {
+ return NGX_OK;
+ }
+#endif
+
+ il = chain;
+
+ while (ngx_buf_size(in->buf) > buf_size) {
+ cl = ngx_alloc_chain_link(pool);
+ if (cl == NULL) {
+ return NGX_ERROR;
+ }
+
+ buf = in->buf;
+
+ /* split a file buf on bufs by the buf_size limit */
+
+ b = ngx_calloc_buf(pool);
+ if (b == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_memcpy(b, buf, sizeof(ngx_buf_t));
+ b->start = NULL;
+ b->end = NULL;
+ b->last_buf = 0;
+ b->last_in_chain = 0;
+
+ if (ngx_buf_in_memory(buf)) {
+ buf->pos += buf_size;
+ b->last = buf->pos;
+ }
+
+ buf->file_pos += buf_size;
+ b->file_last = buf->file_pos;
+
+ cl->buf = b;
+
+ cl->next = in;
+ *il = cl;
+ il = &cl->next;
+ }
+
+ return NGX_OK;
+}
+
diff -r 982678c5c270 -r c8660bcdd8d3 src/http/ngx_http_spdy_filter_module.c
--- a/src/http/ngx_http_spdy_filter_module.c Wed Jun 12 00:41:24 2013 +0900
+++ b/src/http/ngx_http_spdy_filter_module.c Mon Jun 24 18:51:14 2013 +0400
@@ -15,6 +15,9 @@
#define NGX_SPDY_WRITE_BUFFERED NGX_HTTP_WRITE_BUFFERED
+/* it is subject for change */
+/* consider to use NGX_SPDY_MAX_FRAME_SIZE instead ??? */
+#define NGX_SPDY_MAX_FRAME_LENGTH (1024 * 32)
#define ngx_http_spdy_nv_nsize(h) (NGX_SPDY_NV_NLEN_SIZE + sizeof(h) - 1)
#define ngx_http_spdy_nv_vsize(h) (NGX_SPDY_NV_VLEN_SIZE + sizeof(h) - 1)
@@ -676,6 +679,10 @@
cl->buf = b;
*ln = cl;
+ if (ngx_buf_size(b) > NGX_SPDY_MAX_FRAME_LENGTH) {
+ ngx_split_buf_in_chain(r->pool, ln, cl,
NGX_SPDY_MAX_FRAME_LENGTH);
+ }
+
ln = &cl->next;
if (ll->next == NULL) {
@@ -685,24 +692,51 @@
ll = ll->next;
}
- if (size > NGX_SPDY_MAX_FRAME_SIZE) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- "FIXME: chain too big in spdy filter: %O", size);
- return NGX_ERROR;
+ cl->next = NULL;
+ ll = cl = out;
+ size = 0;
+
+ for ( ;; ) {
+ if (size + ngx_buf_size(cl->buf) > NGX_SPDY_MAX_FRAME_LENGTH) {
+ ll->buf->last_in_chain = 1;
+ frame = ngx_http_spdy_filter_get_data_frame(stream,
(size_t)size,
+ ll->buf->last_buf,
out, ll);
+
+ ngx_http_spdy_queue_frame(stream->connection, frame);
+ stream->waiting++;
+ r->main->blocked++;
+
+
+ size = ngx_buf_size(cl->buf);
+ out = cl;
+ ll->next = NULL;
+ ll = cl;
+ if (cl->next == NULL) {
+ break;
+ }
+ cl = cl->next;
+ }
+ else {
+ size += ngx_buf_size(cl->buf);
+ ll = cl;
+ if (cl->next == NULL) {
+ break;
+ }
+ cl = cl->next;
+
+ }
}
- frame = ngx_http_spdy_filter_get_data_frame(stream, (size_t) size,
- b->last_buf, out, cl);
- if (frame == NULL) {
- return NGX_ERROR;
+ if (size > 0) {
+ ll->buf->last_in_chain = 1;
+
+ frame = ngx_http_spdy_filter_get_data_frame(stream, (size_t)size,
+ ll->buf->last_buf,
out, ll);
+ ngx_http_spdy_queue_frame(stream->connection, frame);
+ stream->waiting++;
+ r->main->blocked++;
}
- ngx_http_spdy_queue_frame(stream->connection, frame);
-
- stream->waiting++;
-
- r->main->blocked++;
-
return ngx_http_spdy_filter_send(r->connection, stream);
}
BR/ Yury
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20130624/8286e0cc/attachment.html>
More information about the nginx-devel
mailing list