Thread: Proposal: Limitations of palloc inside checkpointer

Proposal: Limitations of palloc inside checkpointer

From
Ekaterina Sokolova
Date:
Hi, hackers!

Historically, the checkpointer process use palloc() into 
AbsorbSyncRequests() function. Therefore, the checkpointer does not 
expect to receive a request larger than 1 GB.

We encountered a case where the database went into recovery state, after 
applying all wal, the checkpointer process generated an "invalid memory 
alloc request size" error and entered a loop. But it is quite acceptable 
for the recovery state to receive such a large allocation request.

A simple solution to this problem is to use palloc_extended() instead of 
palloc(). But is it safe to allow the checkpointer to allocate so much 
memory at once?

I have proposal to update this memory allocation but I need your ideas 
and advices on how to do it in appropriate way. As an idea, we can 
replace the array with a list of arrays to allocate memory in chunks. As 
a bad idea, we can process a temporary array without locking.

I would be glad to hear your ideas and suggestions about this topic. 
Have a nice day!

-- 
Ekaterina Sokolova
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company



Re: Proposal: Limitations of palloc inside checkpointer

From
Maxim Orlov
Date:


On Tue, 25 Feb 2025 at 22:44, Ekaterina Sokolova <e.sokolova@postgrespro.ru> wrote:
Hi, hackers!

Historically, the checkpointer process use palloc() into
AbsorbSyncRequests() function. Therefore, the checkpointer does not
expect to receive a request larger than 1 GB.

Yeah. And the most unpleasant thing is it won't simply fail with an error or helpful message suggesting a workaround (reduce the amount of shared memory). Checkpointer will just "stuck".

AFAICS, we have a few options:
1. Leave it as it is, but fatal on allocation of the chunk more than 1G.
2. Use palloc_extended with MCXT_ALLOC_HUGE flag.
3. Do not use any allocation and use CheckpointerShmem->requests directly in case of > 1G size of the required allocation.

Case (3) is not an option, in my opinion. So, we following (1) or (2). Personally, I'm for (2), PFA v0 patch.


--
Best regards,
Maxim Orlov.
Attachment

Re: Proposal: Limitations of palloc inside checkpointer

From
Andres Freund
Date:
Hi,

On 2025-02-26 11:46:45 +0300, Maxim Orlov wrote:
> On Tue, 25 Feb 2025 at 22:44, Ekaterina Sokolova <e.sokolova@postgrespro.ru>
> wrote:
> 
> > Hi, hackers!
> >
> > Historically, the checkpointer process use palloc() into
> > AbsorbSyncRequests() function. Therefore, the checkpointer does not
> > expect to receive a request larger than 1 GB.
> 
> 
> Yeah. And the most unpleasant thing is it won't simply fail with an error
> or helpful message suggesting a workaround (reduce the amount of shared
> memory). Checkpointer will just "stuck".
> 
> AFAICS, we have a few options:
> 1. Leave it as it is, but fatal on allocation of the chunk more than 1G.
> 2. Use palloc_extended with MCXT_ALLOC_HUGE flag.
> 3. Do not use any allocation and use CheckpointerShmem->requests directly
> in case of > 1G size of the required allocation.

4) Do compaction incrementally, instead of doing it for all requests at once.

That'd probably be better, because

a) it'll take some time to to compact 10s to 100s of million requests, which
   makes it much more likely that backends will have to perform syncs
   themselves and the lock will be held for an extended period of time

b) allocating gigabytes of memory obviously makes it more likely that you'll
   fail with out-of-memory at runtime or evne get OOM killed.

Greetings,

Andres Freund



Re: Proposal: Limitations of palloc inside checkpointer

From
Maxim Orlov
Date:

On Wed, 26 Feb 2025 at 11:54, Andres Freund <andres@anarazel.de> wrote:

4) Do compaction incrementally, instead of doing it for all requests at once.
Yeah, good idea! I completely forgot about that. Thanks!

--
Best regards,
Maxim Orlov.