Thread: Proposal: Limitations of palloc inside checkpointer
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
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
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
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.