<div dir="ltr"><div><div>Hello!<br><br>I see your point, and I will split the patch to do both actions, <br>on ngx_slab_free_pages() and on allocation when has a failure.<br><br></div>What would be an alternative to not loop on pool->pages?<br>

<br></div><div>Regards,<br>Wandenberg<br></div><br></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, Jul 29, 2013 at 2:11 PM, Maxim Dounin <span dir="ltr"><<a href="mailto:mdounin@mdounin.ru" target="_blank">mdounin@mdounin.ru</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hello!<br>
<div><div class="h5"><br>
On Sat, Jul 27, 2013 at 04:10:51PM -0300, Wandenberg Peixoto wrote:<br>
<br>
> Hello Maxim.<br>
><br>
> I've been looking into those functions and guided by your comments<br>
> made the following patch to merge continuous block of memory.<br>
> Can you check if it is ok?<br>
> Comments are welcome.<br>
><br>
> --- src/core/ngx_slab.c    2013-05-06 07:27:10.000000000 -0300<br>
> +++ src/core/ngx_slab.c    2013-07-27 15:54:55.316995223 -0300<br>
> @@ -687,6 +687,25 @@ ngx_slab_free_pages(ngx_slab_pool_t *poo<br>
>      page->next->prev = (uintptr_t) page;<br>
><br>
>      pool->free.next = page;<br>
> +<br>
> +    for (page = pool->pages; ((page->slab > 0) && (&page[page->slab] <<br>
> (ngx_slab_page_t *) (pool->start - sizeof(ngx_slab_page_t))));) {<br>
> +        ngx_slab_page_t *neighbour = &page[page->slab];<br>
> +        if (((ngx_slab_page_t *) page->prev != NULL) && (page->next !=<br>
> NULL) && ((page->prev & NGX_SLAB_PAGE_MASK) == NGX_SLAB_PAGE) &&<br>
> +            ((ngx_slab_page_t *) neighbour->prev != NULL) &&<br>
> (neighbour->next != NULL) && ((neighbour->prev & NGX_SLAB_PAGE_MASK) ==<br>
> NGX_SLAB_PAGE)) {<br>
> +<br>
> +            page->slab += neighbour->slab;<br>
> +<br>
> +            ((ngx_slab_page_t *) neighbour->prev)->next = neighbour->next;<br>
> +            neighbour->next->prev = neighbour->prev;<br>
> +<br>
> +            neighbour->slab = NGX_SLAB_PAGE_FREE;<br>
> +            neighbour->prev = (uintptr_t) &pool->free;<br>
> +            neighbour->next = &pool->free;<br>
> +            continue;<br>
> +        }<br>
> +<br>
> +        page += ((page->prev & NGX_SLAB_PAGE_MASK) == NGX_SLAB_PAGE) ?<br>
> page->slab : 1;<br>
> +    }<br>
>  }<br>
<br>
</div></div>The patch doesn't look right (well, may be it works - but at least it's<br>
not something I would like to see committed).<br>
<br>
The pool->pages isn't something you should iterate though, it's<br>
just a preallocated storage space for ngx_slab_page_t structures.<br>
<br>
Additionally, doing a full merge of all free blocks on a free<br>
operation looks too much.  It might be something we want to do on<br>
allocation failure, but not on a normal path in<br>
ngx_slab_free_pages().  And/or something lightweight may be done<br>
in ngx_slab_free_pages(), e.g., checking if pages following pages<br>
we are freeing are free too, and merging them in this case.<br>
<div class="HOEnZb"><div class="h5"><br>
><br>
><br>
><br>
> Regards,<br>
> Wandenberg<br>
><br>
><br>
> On Mon, Jul 1, 2013 at 8:36 AM, Maxim Dounin <<a href="mailto:mdounin@mdounin.ru">mdounin@mdounin.ru</a>> wrote:<br>
><br>
> > Hello!<br>
> ><br>
> > On Fri, Jun 28, 2013 at 10:36:39PM -0300, Wandenberg Peixoto wrote:<br>
> ><br>
> > > Hi,<br>
> > ><br>
> > > I'm trying to understand how the shared memory pool works inside the<br>
> > Nginx.<br>
> > > To do that, I made a very small module which create a shared memory zone<br>
> > > with 2097152 bytes,<br>
> > > and allocating and freeing blocks of memory, starting from 0 and<br>
> > increasing<br>
> > > by 1kb until the allocation fails.<br>
> > ><br>
> > > The strange parts to me were:<br>
> > > - the maximum block I could allocate was 128000 bytes<br>
> > > - each time the allocation fails, I started again from 0, but the maximum<br>
> > > allocated block changed with the following profile<br>
> > > 128000<br>
> > > 87040<br>
> > > 70656<br>
> > > 62464<br>
> > > 58368<br>
> > > 54272<br>
> > > 50176<br>
> > > 46080<br>
> > > 41984<br>
> > > 37888<br>
> > > 33792<br>
> > > 29696<br>
> > ><br>
> > > This is the expected behavior?<br>
> > > Can anyone help me explaining how shared memory works?<br>
> > > I have another module which do an intensive shared memory usage, and<br>
> > > understanding this can help me improve it solving some "no memory"<br>
> > messages.<br>
> > ><br>
> > > I put the code in attach.<br>
> ><br>
> > I've looked into this, and the behaviour is expected as per<br>
> > nginx slab allocator code and the way you do allocations in your<br>
> > test.<br>
> ><br>
> > Increasing allocations of large blocks immediately followed by<br>
> > freeing them result in free memory blocks split into smaller<br>
> > blocks, eventually resulting in at most page size allocations<br>
> > being possible.  Take a look at ngx_slab_alloc_pages() and<br>
> > ngx_slab_free_pages() for details.<br>
> ><br>
> > Note that slab allocator nginx uses for allocations in shared<br>
> > memory is designed mostly for small allocations.  It works well<br>
> > for allocations less than page size, but large allocations support<br>
> > is very simple.  Probably it should be improved, but as of now<br>
> > nothing in nginx uses large allocations in shared memory.<br>
> ><br>
> > --<br>
> > Maxim Dounin<br>
> > <a href="http://nginx.org/en/donation.html" target="_blank">http://nginx.org/en/donation.html</a><br>
> ><br>
> > _______________________________________________<br>
> > nginx-devel mailing list<br>
> > <a href="mailto:nginx-devel@nginx.org">nginx-devel@nginx.org</a><br>
> > <a href="http://mailman.nginx.org/mailman/listinfo/nginx-devel" target="_blank">http://mailman.nginx.org/mailman/listinfo/nginx-devel</a><br>
> ><br>
<br>
<br>
> _______________________________________________<br>
> nginx-devel mailing list<br>
> <a href="mailto:nginx-devel@nginx.org">nginx-devel@nginx.org</a><br>
> <a href="http://mailman.nginx.org/mailman/listinfo/nginx-devel" target="_blank">http://mailman.nginx.org/mailman/listinfo/nginx-devel</a><br>
<br>
<br>
--<br>
Maxim Dounin<br>
<a href="http://nginx.org/en/donation.html" target="_blank">http://nginx.org/en/donation.html</a><br>
<br>
_______________________________________________<br>
nginx-devel mailing list<br>
<a href="mailto:nginx-devel@nginx.org">nginx-devel@nginx.org</a><br>
<a href="http://mailman.nginx.org/mailman/listinfo/nginx-devel" target="_blank">http://mailman.nginx.org/mailman/listinfo/nginx-devel</a><br>
</div></div></blockquote></div><br></div>