Re: Parallel vacuum: workers together with leader could overrun cost budget

From: Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com>
To: Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>
Cc: Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Parallel vacuum: workers together with leader could overrun cost budget
Date: 2026-10-23 00:52:40
Message-ID: 3C2BE659-F2F0-4B91-AC5B-A1ABC39A6948@gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

> On Oct 23, 2026, at 03:30, Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com> wrote:
>
> Hi,
>
> On Wed, Oct 21, 2026 at 7:32 PM Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com> wrote:
>>
>> After reading v2, I have a small concern.
>>
>> In the VacuumSharedCostBalance != NULL path, the sleep cap is vacuum_cost_delay * 4 * nworkers. Say vacuum_cost_delay=100ms and nworkers=16; then the sleep time could be 6.4 seconds. Passing such a long delay to pg_usleep() seems concerning because its header comment explicitly says:
>
> Nice catch! You are right. With a max cost delay of 100ms today, the
> existing cap is no more than 400ms. And it looks like other
> pg_usleep() callers in core will not wait more than 1s at once (except
> the auth delays, which are developer options anyway). And per the
> comment in WaitExceedsMaxStandbyDelay(), it seems that waiting more
> than 1s with pg_usleep() is the "too long" beyond which backends lose
> prompt response to latches and signals.
>
> I think there are a couple of ways to handle this:
>
> 1/ Keep the cap at cost_delay * 4 * nworkers, but replace pg_usleep()
> with WaitLatch() in 400ms steps (or even 1s steps).
>

The header comment of pg_usleep() also suggests using WaitLatch() with a timeout for long sleeps. However, one issue is that WaitLatch() takes a timeout in milliseconds, while vacuum needs microsecond precision.

> 2/ Cap the delay per worker at 1s (similar to
> WaitExceedsMaxStandbyDelay()) i.e. Min(Min(msec, cost_delay * 4 *
> nworkers), 1000). This still looks fine, and it's better than today's
> 400ms limit.
>

Wouldn't the 1-second cap still allow the cost budget to be exceeded in some cases, which is exactly what this patch is trying to fix? If so, wouldn't that leave the fix incomplete?

> I prefer option 2, with a 1s cap per worker. Thoughts?
>
> --
> Bharath Rupireddy
> Amazon Web Services: https://aws.amazon.com

I'm thinking that maybe we could combine WaitLatch() and pg_usleep(). Use WaitLatch() to sleep for the whole-millisecond portion, and leave the remaining sub-millisecond portion to pg_usleep(), so we can preserve the precision without sacrificing responsiveness.

The pseudocode would look something like this:
```
while (remaining_us > 0)
{
CHECK_FOR_INTERRUPTS();

if (remaining_us >= 1000)
{
(void) WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH,
remaining_us / 1000,
WAIT_EVENT_VACUUM_DELAY);

ResetLatch(MyLatch);
}
else
{
pg_usleep(remaining_us);
}

/* Recalculate remaining_us. */
remaining_us = ...
}
```

Best regards,
--
Chao Li (Evan)
HighGo Software Co., Ltd.
https://www.highgo.com/

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Chao Li 2026-10-23 01:06:53 Re: DOCS - CREATE PUBLICATION wording re 'ONLY' for partitioned tables.
Previous Message Bharath Rupireddy 2026-10-23 00:51:34 Re: Parallel autovacuum: leader crashes when no DSM segment can be created