resowner "cold start" overhead - Mailing list pgsql-hackers

From Andres Freund
Subject resowner "cold start" overhead
Date
Msg-id 20221029200025.w7bvlgvamjfo6z44@awork3.anarazel.de
Whole thread Raw
Responses Re: resowner "cold start" overhead
List pgsql-hackers
Hi,

As part of [1] I made IOs-in-progress be tracked by resowner.c. Benchmarking
unfortunately showed that to have a small impact on workloads that often have
to read data, but where that data is guaranteed to be in the kernel cache.

I was a bit surprised, given that we also use the resowner.c mechanism for
buffer pins, which are obviously more common. But those (and e.g. relache
references) actually also show up in profiles...

The obvious answeriis to have a few "embedded" elements in each ResourceArray,
so that no allocation is needed for the first few remembered objects in each
category.  In a prototype I went with four, since that avoided allocations for
trivial queries. That works nicely, delivering small but measurable speedups.

However, that approach does increase the size of a ResourceOwner. I don't know
if it matters that much, my prototype made the size go from 544 to 928 bytes -
which afaict would basically be free currently, because of aset.c rounding
up. But it'd take just two more ResourceArrays to go above that boundary.

struct ResourceArray {
        Datum *                    itemsarr;             /*     0     8 */
        Datum                      invalidval;           /*     8     8 */
        uint32                     capacity;             /*    16     4 */
        uint32                     nitems;               /*    20     4 */
        uint32                     maxitems;             /*    24     4 */
        uint32                     lastidx;              /*    28     4 */
        Datum                      initialarr[4];        /*    32    32 */

        /* size: 64, cachelines: 1, members: 7 */
};


One way to reduce the size increase would be to use the space for initialarr
to store variables we don't need while initialarr is used. E.g. itemsarr,
maxitems, lastarr are candidates.  But I suspect that the code complication
isn't worth it.


A different approach could be to not go for the "embedded initial elements"
approach, but instead to not delete resource owners / resource arrays inside
ResourceOwnerDelete(). We could stash them in a bounded list of resource
owners, to be reused by ResourceOwnerCreate().  We do end up creating a
several resource owners even for the simplest queries.

The advantage of that scheme is that it'd save more and that we'd only reserve
space for ResourceArrays that are actually used in the current workload -
often the majority of arrays won't be.

A potential problem would be that we don't want to use the "hashing" style
ResourceArrays forever, I don't think they'll be as fast for other cases. But
we could reset the arrays when they get large.

Greetings,

Andres Freund

https://www.postgresql.org/message-id/20221029025420.eplyow6k7tgu6he3%40awork3.anarazel.de



pgsql-hackers by date:

Previous
From: Andres Freund
Date:
Subject: Re: refactoring relation extension and BufferAlloc(), faster COPY
Next
From: Noah Misch
Date:
Subject: Re: has_wal_read_bug