Mercurial > hg > nginx
comparison src/core/ngx_slab.c @ 5718:c46657e391a3
Core: slab allocator free pages defragmentation.
Large allocations from a slab pool result in free page blocks being fragmented,
eventually leading to a situation when no further allocation larger than a page
size are possible from the pool. While this isn't a problem for nginx itself,
it is known to be bad for various 3rd party modules. Fix is to merge adjacent
blocks of free pages in the ngx_slab_free_pages() function.
Prodded by Wandenberg Peixoto and Yichun Zhang.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Tue, 03 Jun 2014 17:53:03 +0400 |
parents | 5024d29354f1 |
children | 25ade23cf281 |
comparison
equal
deleted
inserted
replaced
5717:efc84a5723b3 | 5718:c46657e391a3 |
---|---|
127 if (m > 0) { | 127 if (m > 0) { |
128 pages -= m; | 128 pages -= m; |
129 pool->pages->slab = pages; | 129 pool->pages->slab = pages; |
130 } | 130 } |
131 | 131 |
132 pool->last = pool->pages + pages; | |
133 | |
132 pool->log_nomem = 1; | 134 pool->log_nomem = 1; |
133 pool->log_ctx = &pool->zero; | 135 pool->log_ctx = &pool->zero; |
134 pool->zero = '\0'; | 136 pool->zero = '\0'; |
135 } | 137 } |
136 | 138 |
624 for (page = pool->free.next; page != &pool->free; page = page->next) { | 626 for (page = pool->free.next; page != &pool->free; page = page->next) { |
625 | 627 |
626 if (page->slab >= pages) { | 628 if (page->slab >= pages) { |
627 | 629 |
628 if (page->slab > pages) { | 630 if (page->slab > pages) { |
631 page[page->slab - 1].prev = (uintptr_t) &page[pages]; | |
632 | |
629 page[pages].slab = page->slab - pages; | 633 page[pages].slab = page->slab - pages; |
630 page[pages].next = page->next; | 634 page[pages].next = page->next; |
631 page[pages].prev = page->prev; | 635 page[pages].prev = page->prev; |
632 | 636 |
633 p = (ngx_slab_page_t *) page->prev; | 637 p = (ngx_slab_page_t *) page->prev; |
670 | 674 |
671 static void | 675 static void |
672 ngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page, | 676 ngx_slab_free_pages(ngx_slab_pool_t *pool, ngx_slab_page_t *page, |
673 ngx_uint_t pages) | 677 ngx_uint_t pages) |
674 { | 678 { |
675 ngx_slab_page_t *prev; | 679 ngx_uint_t type; |
680 ngx_slab_page_t *prev, *join; | |
676 | 681 |
677 page->slab = pages--; | 682 page->slab = pages--; |
678 | 683 |
679 if (pages) { | 684 if (pages) { |
680 ngx_memzero(&page[1], pages * sizeof(ngx_slab_page_t)); | 685 ngx_memzero(&page[1], pages * sizeof(ngx_slab_page_t)); |
682 | 687 |
683 if (page->next) { | 688 if (page->next) { |
684 prev = (ngx_slab_page_t *) (page->prev & ~NGX_SLAB_PAGE_MASK); | 689 prev = (ngx_slab_page_t *) (page->prev & ~NGX_SLAB_PAGE_MASK); |
685 prev->next = page->next; | 690 prev->next = page->next; |
686 page->next->prev = page->prev; | 691 page->next->prev = page->prev; |
692 } | |
693 | |
694 join = page + page->slab; | |
695 | |
696 if (join < pool->last) { | |
697 type = join->prev & NGX_SLAB_PAGE_MASK; | |
698 | |
699 if (type == NGX_SLAB_PAGE) { | |
700 | |
701 if (join->next != NULL) { | |
702 pages += join->slab; | |
703 page->slab += join->slab; | |
704 | |
705 prev = (ngx_slab_page_t *) (join->prev & ~NGX_SLAB_PAGE_MASK); | |
706 prev->next = join->next; | |
707 join->next->prev = join->prev; | |
708 | |
709 join->slab = NGX_SLAB_PAGE_FREE; | |
710 join->next = NULL; | |
711 join->prev = NGX_SLAB_PAGE; | |
712 } | |
713 } | |
714 } | |
715 | |
716 if (page > pool->pages) { | |
717 join = page - 1; | |
718 type = join->prev & NGX_SLAB_PAGE_MASK; | |
719 | |
720 if (type == NGX_SLAB_PAGE) { | |
721 | |
722 if (join->slab == NGX_SLAB_PAGE_FREE) { | |
723 join = (ngx_slab_page_t *) (join->prev & ~NGX_SLAB_PAGE_MASK); | |
724 } | |
725 | |
726 if (join->next != NULL) { | |
727 pages += join->slab; | |
728 join->slab += page->slab; | |
729 | |
730 prev = (ngx_slab_page_t *) (join->prev & ~NGX_SLAB_PAGE_MASK); | |
731 prev->next = join->next; | |
732 join->next->prev = join->prev; | |
733 | |
734 page->slab = NGX_SLAB_PAGE_FREE; | |
735 page->next = NULL; | |
736 page->prev = NGX_SLAB_PAGE; | |
737 | |
738 page = join; | |
739 } | |
740 } | |
741 } | |
742 | |
743 if (pages) { | |
744 page[pages].prev = (uintptr_t) page; | |
687 } | 745 } |
688 | 746 |
689 page->prev = (uintptr_t) &pool->free; | 747 page->prev = (uintptr_t) &pool->free; |
690 page->next = pool->free.next; | 748 page->next = pool->free.next; |
691 | 749 |