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