Mercurial > hg > nginx
comparison src/http/modules/ngx_http_sub_filter_module.c @ 6605:f379b32e4733
Sub filter: eliminate unnecessary buffering.
Previously, when a buffer was processed by the sub filter, its final bytes
could be buffered by the filter even if they don't match any pattern.
This happened because the Boyer-Moore algorithm, employed by the sub filter
since b9447fc457b4 (1.9.4), matches the last characters of patterns prior to
checking other characters. If the last character is out of scope, initial
bytes of a potential match are buffered until the last character is available.
Now, after receiving a flush or recycled buffer, the filter performs
additional checks to reduce the number of buffered bytes. The potential match
is checked against the initial parts of all patterns. Non-matching bytes are
not buffered. This improves processing of a chunked response from upstream
by sending the entire chunks without buffering unless a partial match is found
at the end of a chunk.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Sat, 02 Jul 2016 15:59:53 +0300 |
parents | 0e0adbbc8752 |
children | f18c285c2e59 |
comparison
equal
deleted
inserted
replaced
6604:0e0adbbc8752 | 6605:f379b32e4733 |
---|---|
81 | 81 |
82 | 82 |
83 static ngx_int_t ngx_http_sub_output(ngx_http_request_t *r, | 83 static ngx_int_t ngx_http_sub_output(ngx_http_request_t *r, |
84 ngx_http_sub_ctx_t *ctx); | 84 ngx_http_sub_ctx_t *ctx); |
85 static ngx_int_t ngx_http_sub_parse(ngx_http_request_t *r, | 85 static ngx_int_t ngx_http_sub_parse(ngx_http_request_t *r, |
86 ngx_http_sub_ctx_t *ctx); | 86 ngx_http_sub_ctx_t *ctx, ngx_uint_t flush); |
87 static ngx_int_t ngx_http_sub_match(ngx_http_sub_ctx_t *ctx, ngx_int_t start, | 87 static ngx_int_t ngx_http_sub_match(ngx_http_sub_ctx_t *ctx, ngx_int_t start, |
88 ngx_str_t *m); | 88 ngx_str_t *m); |
89 | 89 |
90 static char * ngx_http_sub_filter(ngx_conf_t *cf, ngx_command_t *cmd, | 90 static char * ngx_http_sub_filter(ngx_conf_t *cf, ngx_command_t *cmd, |
91 void *conf); | 91 void *conf); |
285 ngx_http_sub_body_filter(ngx_http_request_t *r, ngx_chain_t *in) | 285 ngx_http_sub_body_filter(ngx_http_request_t *r, ngx_chain_t *in) |
286 { | 286 { |
287 ngx_int_t rc; | 287 ngx_int_t rc; |
288 ngx_buf_t *b; | 288 ngx_buf_t *b; |
289 ngx_str_t *sub; | 289 ngx_str_t *sub; |
290 ngx_uint_t flush, last; | |
290 ngx_chain_t *cl; | 291 ngx_chain_t *cl; |
291 ngx_http_sub_ctx_t *ctx; | 292 ngx_http_sub_ctx_t *ctx; |
292 ngx_http_sub_match_t *match; | 293 ngx_http_sub_match_t *match; |
293 ngx_http_sub_loc_conf_t *slcf; | 294 ngx_http_sub_loc_conf_t *slcf; |
294 | 295 |
326 } | 327 } |
327 | 328 |
328 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 329 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
329 "http sub filter \"%V\"", &r->uri); | 330 "http sub filter \"%V\"", &r->uri); |
330 | 331 |
332 flush = 0; | |
333 last = 0; | |
334 | |
331 while (ctx->in || ctx->buf) { | 335 while (ctx->in || ctx->buf) { |
332 | 336 |
333 if (ctx->buf == NULL) { | 337 if (ctx->buf == NULL) { |
334 ctx->buf = ctx->in->buf; | 338 ctx->buf = ctx->in->buf; |
335 ctx->in = ctx->in->next; | 339 ctx->in = ctx->in->next; |
336 ctx->pos = ctx->buf->pos; | 340 ctx->pos = ctx->buf->pos; |
337 } | 341 } |
338 | 342 |
343 if (ctx->buf->flush || ctx->buf->recycled) { | |
344 flush = 1; | |
345 } | |
346 | |
347 if (ctx->in == NULL) { | |
348 last = flush; | |
349 } | |
350 | |
339 b = NULL; | 351 b = NULL; |
340 | 352 |
341 while (ctx->pos < ctx->buf->last) { | 353 while (ctx->pos < ctx->buf->last) { |
342 | 354 |
343 rc = ngx_http_sub_parse(r, ctx); | 355 rc = ngx_http_sub_parse(r, ctx, last); |
344 | 356 |
345 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 357 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
346 "parse: %i, looked: \"%V\" %p-%p", | 358 "parse: %i, looked: \"%V\" %p-%p", |
347 rc, &ctx->looked, ctx->copy_start, ctx->copy_end); | 359 rc, &ctx->looked, ctx->copy_start, ctx->copy_end); |
348 | 360 |
590 return rc; | 602 return rc; |
591 } | 603 } |
592 | 604 |
593 | 605 |
594 static ngx_int_t | 606 static ngx_int_t |
595 ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx) | 607 ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx, |
608 ngx_uint_t flush) | |
596 { | 609 { |
597 u_char *p, c; | 610 u_char *p, c; |
598 ngx_str_t *m; | 611 ngx_str_t *m; |
599 ngx_int_t offset, start, next, end, len, rc; | 612 ngx_int_t offset, start, next, end, len, rc; |
600 ngx_uint_t shift, i, j; | 613 ngx_uint_t shift, i, j; |
602 ngx_http_sub_tables_t *tables; | 615 ngx_http_sub_tables_t *tables; |
603 ngx_http_sub_loc_conf_t *slcf; | 616 ngx_http_sub_loc_conf_t *slcf; |
604 | 617 |
605 slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); | 618 slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); |
606 tables = ctx->tables; | 619 tables = ctx->tables; |
620 match = ctx->matches->elts; | |
607 | 621 |
608 offset = ctx->offset; | 622 offset = ctx->offset; |
609 end = ctx->buf->last - ctx->pos; | 623 end = ctx->buf->last - ctx->pos; |
610 | 624 |
611 if (ctx->once) { | 625 if (ctx->once) { |
628 } | 642 } |
629 | 643 |
630 /* a potential match */ | 644 /* a potential match */ |
631 | 645 |
632 start = offset - (ngx_int_t) tables->min_match_len + 1; | 646 start = offset - (ngx_int_t) tables->min_match_len + 1; |
633 match = ctx->matches->elts; | |
634 | 647 |
635 i = ngx_max(tables->index[c], ctx->index); | 648 i = ngx_max(tables->index[c], ctx->index); |
636 j = tables->index[c + 1]; | 649 j = tables->index[c + 1]; |
637 | 650 |
638 while (i != j) { | 651 while (i != j) { |
667 i++; | 680 i++; |
668 } | 681 } |
669 | 682 |
670 offset++; | 683 offset++; |
671 ctx->index = 0; | 684 ctx->index = 0; |
685 } | |
686 | |
687 if (flush) { | |
688 for ( ;; ) { | |
689 start = offset - (ngx_int_t) tables->min_match_len + 1; | |
690 | |
691 if (start >= end) { | |
692 break; | |
693 } | |
694 | |
695 for (i = 0; i < ctx->matches->nelts; i++) { | |
696 m = &match[i].match; | |
697 | |
698 if (ngx_http_sub_match(ctx, start, m) == NGX_AGAIN) { | |
699 goto again; | |
700 } | |
701 } | |
702 | |
703 offset++; | |
704 } | |
672 } | 705 } |
673 | 706 |
674 again: | 707 again: |
675 | 708 |
676 ctx->offset = offset; | 709 ctx->offset = offset; |