Re: Reducing the chunk header sizes on all memory context types
Tom Lane <tgl@sss.pgh.pa.us>
I wrote:
> FreeBSD 13.0, arm64: Usually the low-order nibble is 0000 or 1111,
> but for some smaller values of N it sometimes comes up as 0010.
> NetBSD 9.2, amd64: results similar to FreeBSD.
I looked into NetBSD's malloc.c, and what I discovered is that
their implementation doesn't have any chunk headers: chunks of
the same size are allocated consecutively within pages, and all
the bookkeeping data is somewhere else. Presumably FreeBSD is
the same. So the apparent special case with 0010 is an illusion,
even though I saw it on two different machines (maybe it's a
specific value that we're allocating??) The most likely case
is 0000 due to the immediately previous word having never been
used (note that like palloc, they round chunk sizes up to powers
of two, so unused space at the end of a chunk is common). I'm
not sure whether the cases I saw with 1111 are chance artifacts
or reflect some real mechanism, but probably the former. I
thought for a bit that that might be the effects of wipe_mem
on the previous chunk, but palloc'd storage would never share
the same page as malloc'd storage under this allocator, because
we grab it from malloc in larger-than-page chunks.
However ... after looking into glib's malloc.c, I find that
it does use a chunk header, and very conveniently the three bits
that we care about are flag bits (at least on 64-bit machines):
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of previous chunk, if unallocated (P clear) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of chunk, in bytes |A|M|P|
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| User data starts here... .
The A bit is only used when threading, and hence should always
be zero in our usage. The M bit only gets set in chunks large
enough to be separately mmap'd, so when it is set P must be 0.
If M is not set then P seems to usually be 1, although it could
be 0. So the three possibilities for what we can see under
glibc are 000, 001, 010 (the last only occuring for chunks
larger than 128K). This squares with experimental results on
my machine --- I'd not thought to try sizes above 100K before.
So I'm still inclined to leave 001 and 010 both unused, but the
reason why is different than I thought before.
Going forward, we could commandeer 010 if we need to without losing
very much debuggability, since malloc'ing more than 128K in a chunk
won't happen often.
regards, tom lane
Commits
-
Harden memory context allocators against bogus chunk pointers.
- 0e87dfe46443 16.0 landed
-
Improve our ability to detect bogus pointers passed to pfree et al.
- 80ef92675823 16.0 landed
-
Remove MemoryContextContains().
- 9543eff5e015 16.0 landed
-
Remove uses of MemoryContextContains in nodeAgg.c and nodeWindowAgg.c.
- 42b746d4c982 16.0 landed
-
Temporarily make MemoryContextContains return false
- b76fb6c2a99e 16.0 landed
-
Make MemoryContextContains work correctly again
- 5265e91fd10d 16.0 landed
-
Make more effort to put a sentinel at the end of allocated memory
- 0e480385ec59 16.0 landed
-
Fix some possibly latent bugs in slab.c
- 258b0411b243 10.23 landed
- 1b1154396798 11.18 landed
- f249f1026f71 12.13 landed
- 210bece161b0 13.9 landed
- 6ec896109254 14.6 landed
- c4e861b7bba3 15.0 landed
-
Various cleanups of the new memory context header code
- 05f908423695 16.0 landed
-
Revert "Add missing padding from MemoryChunk struct"
- 5495796ad12a 16.0 landed
-
Use MAXALIGN() in calculations using sizeof(SlabBlock)
- d5ee4db0eaf6 16.0 landed
-
Add missing padding from MemoryChunk struct
- df0f4feef8de 16.0 landed
-
Improve performance of and reduce overheads of memory management
- c6e0fe1f2a08 16.0 landed