From f77cf0f831df74e5e2d11910cea395f5f4541d25 Mon Sep 17 00:00:00 2001 From: Sami Imseih Date: Thu, 25 Jul 2024 20:28:35 +0000 Subject: [PATCH 1/1] vaccum_delay with absolute time nanosleep --- src/backend/commands/vacuum.c | 49 ++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 48f8eab202..a753d6984f 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -116,6 +116,53 @@ static bool vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params, static double compute_parallel_delay(void); static VacOptValue get_vacoptval_from_boolean(DefElem *def); static bool vac_tid_reaped(ItemPointer itemptr, void *state); +static void vacuum_sleep(double msec); + +static +void +vacuum_sleep(double msec) +{ + long microsec = msec * 1000; + + if (microsec > 0) + { +#ifndef WIN32 + /* + * We allow nanosleep to handle interrupts and retry with the + * remaining time. However, frequent interruptions and restarts of the + * nanosleep calls can substantially lead to drift in the time when + * the sleep finally completes. To deal with this, we break out of the + * loop whenever the elapsed time exceeds the requested time. + */ + struct timespec delay; + struct timespec remain; + struct instr_time start_time; + + INSTR_TIME_SET_CURRENT(start_time); + + delay.tv_sec = microsec / 1000000L; + delay.tv_nsec = (microsec % 1000000L) * 1000; + + while (nanosleep(&delay, &remain) == -1 && errno == EINTR) + { + struct instr_time current_time; + struct instr_time elapsed_time; + + INSTR_TIME_SET_CURRENT(current_time); + + INSTR_TIME_SET_ZERO(elapsed_time); + INSTR_TIME_ACCUM_DIFF(elapsed_time, current_time, start_time); + + if (INSTR_TIME_GET_MICROSEC(elapsed_time) >= microsec) + break; + + delay = remain; + } +#else + SleepEx((microsec < 500 ? 1 : (microsec + 500) / 1000), FALSE); +#endif + } +} /* * GUC check function to ensure GUC value specified is within the allowable @@ -2384,7 +2431,7 @@ vacuum_delay_point(void) msec = vacuum_cost_delay * 4; pgstat_report_wait_start(WAIT_EVENT_VACUUM_DELAY); - pg_usleep(msec * 1000); + vacuum_sleep(msec); pgstat_report_wait_end(); /* -- 2.43.0