Re: Avoid stack frame setup in performance critical routines using tail calls
David Rowley <dgrowleyml@gmail.com>
From: David Rowley <dgrowleyml@gmail.com>
To: Andres Freund <andres@anarazel.de>
Cc: pgsql-hackers@postgresql.org, Robert Haas <robertmhaas@gmail.com>, Michael Paquier <michael.paquier@gmail.com>, Tomas Vondra <tv@fuzzy.cz>
Date: 2024-02-26T07:42:34Z
Lists: pgsql-hackers
Attachments
- v4-0001-Optimize-palloc-etc-to-allow-sibling-calls.patch (text/plain) patch v4-0001
- v4-0002-Optimize-AllocSetAlloc-by-separating-hot-from-col.patch (text/plain) patch v4-0002
- v4-0003-Make-unsetting-the-isReset-flag-the-MemoryContext.patch (text/plain) patch v4-0003
- Function-to-test-palloc-pfree-performance.patch.txt (text/plain)
- benchmark_results.png (image/png)
On Fri, 23 Feb 2024 at 11:53, Andres Freund <andres@anarazel.de> wrote:
> > @@ -1061,6 +1072,16 @@ MemoryContextAlloc(MemoryContext context, Size size)
> >
> > context->isReset = false;
> >
>
> For a moment this made me wonder if we could move the isReset handling into
> the allocator slow paths as well - it's annoying to write that bit (and thus
> dirty the cacheline) over and ove. But it'd be somewhat awkward due to
> pre-allocated blocks. So that'd be a larger change better done separately.
It makes sense to do this, but on looking closer for aset.c, it seems
like the only time we can avoid un-setting the isReset flag is when
allocating from the freelist. We must unset it for large allocations
and for allocations that don't fit onto the existing block (the
exiting block could be the keeper block) and for allocations that
require a new block.
With the current arrangement of code in generation.c, I didn't see any
path we could skip doing context->isReset = false.
For slab.c, it's very easy and we can skip setting the isReset in most cases.
I've attached the patches I benchmarked against 449e798c7 and also the
patch I used to add a function to exercise palloc.
The query I ran was:
select chksz,mtype,pg_allocate_memory_test_reset(chksz, 1024*1024,
1024*1024*1024, mtype)
from (values(8),(16),(32),(64)) sizes(chksz),
(values('aset'),('generation'),('slab')) cxt(mtype)
order by mtype,chksz;
David
Commits
-
Optimize GenerationAlloc() and SlabAlloc()
- a0cd95448067 17.0 landed
-
Refactor AllocSetAlloc(), separating hot and cold paths
- 413c18401dcc 17.0 landed
-
Adjust memory allocation functions to allow sibling calls
- 743112a2e993 17.0 landed