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

From: Manu <manuelreyesbravo(at)gmail(dot)com>
To: surya poondla <suryapoondla4(at)gmail(dot)com>
Cc: Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com>, 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-24 00:21:17
Message-ID: 179280127747.1651045.11755101880776010984@gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi Surya,

On Fri, Oct 23, 2026 at 2:50 PM surya poondla <suryapoondla4(at)gmail(dot)com> wrote:
> It's bounded though, a capped process
> gets at most roughly 1.6-1.8x its share there, and only once nworkers *
> cost_delay gets near 1s.

I measured it on master + v2 with vacuum_cost_delay = 100ms, 20 btree
indexes and 10% of the rows deleted, N = 3. Cost spent per second, as
a multiple of the budget:

limit 200, PARALLEL 4/8/16: 1 s cap 1.08x to 1.18x, v2 1.10x to 1.17x
limit 20, PARALLEL 4: 1 s cap 1.05x, v2 1.05x
limit 20, PARALLEL 16: 1 s cap 1.54x to 1.55x, v2 1.07x

So the cap shows up only with many workers and a small limit, and it
stays within your bound.

> Regarding the WaitLatch() for HEAD, worth remembering it was tried before
> (4753ef37e0e) and reverted in 720de00af49 because the millisecond timeout
> broke fractional cost_delay.

Chao's loop as posted sleeps the whole milliseconds in WaitLatch() and
the rest in pg_usleep(). Fractional delays matched v2: 0.96x to 0.97x
for both at 2.5ms, 0.92x to 0.95x for both at 0.5ms. It also held the
budget in the runs above: 1.02x to 1.04x at limit 200, 1.03x at
limit 20.

One thing is independent of the cap: at 100ms, v2 itself runs at
1.10x to 1.19x. On Unix pg_usleep() is nanosleep()
(src/port/pgsleep.c:50), which returns early when a signal handler
runs, and v2 does not go back to sleep. The leader got 25 SIGUSR1 at
PARALLEL 4 and 47 at PARALLEL 16 during one VACUUM (VERBOSE), one per
worker message (src/backend/libpq/pqmq.c:187), e.g. the index
progress update (vacuumparallel.c:1217). A diagnostic build of v2
that only resumes the interrupted sleep gives 1.02x to 1.03x. At 10ms
with a larger table v2 measured 1.00x, in line with your runs.

On interrupts, pg_cancel_backend() took 5.0 to 16.1 ms with v2 and
8.5 to 14.9 ms with the loop (N = 10). If the cancel lands right
before the sleep (forced with gdb), v2 sleeps the full 6.8 s at
PARALLEL 16, the 1 s cap about 1 s, and the loop 0.4 to 3.2 ms.

Setup and all values are in the attached measurements.txt. One Linux
machine with other jobs running; the ratios repeat within 0.08 across
rounds. Windows not measured.

regards,
Manu

Attachment Content-Type Size
measurements.txt text/plain 4.5 KB

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Manu 2026-10-24 00:29:36 Re: [(known) BUG] DELETE/UPDATE more than one row in partitioned foreign table
Previous Message Manu 2026-10-24 00:19:59 Re: [PG19] Promotion hangs behind a backend blocked on a stuck client