postgresql/src/include/storage/pmsignal.h
Thomas Munro d1c01b79d4 aio: Adjust I/O worker pool automatically.
The size of the I/O worker pool used to implement io_method=worker was
previously controlled by the io_workers setting, defaulting to 3.  It
was hard to know how to tune it effectively.  That is replaced with:

  io_min_workers=2
  io_max_workers=8 (up to 32)
  io_worker_idle_timeout=60s
  io_worker_launch_interval=100ms

The pool is automatically sized within the configured range according to
recent variation in demand.  It grows when existing workers detect that
latency might be introduced by queuing, and shrinks when the
highest-numbered worker is idle for too long.  Work was already
concentrated into low-numbered workers in anticipation of this logic.

The logic for waking extra workers now also tries to measure and reduce
the number of spurious wakeups, though they are not entirely eliminated.

Reviewed-by: Andres Freund <andres@anarazel.de>
Reviewed-by: Dmitry Dolgov <9erthalion6@gmail.com>
Reviewed-by: Nazir Bilal Yavuz <byavuz81@gmail.com>
Discussion: https://postgr.es/m/CA%2BhUKG%2Bm4xV0LMoH2c%3DoRAdEXuCnh%2BtGBTWa7uFeFMGgTLAw%2BQ%40mail.gmail.com
2026-04-08 19:08:32 +12:00

109 lines
3.5 KiB
C

/*-------------------------------------------------------------------------
*
* pmsignal.h
* routines for signaling between the postmaster and its child processes
*
*
* Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/storage/pmsignal.h
*
*-------------------------------------------------------------------------
*/
#ifndef PMSIGNAL_H
#define PMSIGNAL_H
#include <signal.h>
#ifdef HAVE_SYS_PRCTL_H
#include <sys/prctl.h>
#endif
#ifdef HAVE_SYS_PROCCTL_H
#include <sys/procctl.h>
#endif
/*
* Reasons for signaling the postmaster. We can cope with simultaneous
* signals for different reasons. If the same reason is signaled multiple
* times in quick succession, however, the postmaster is likely to observe
* only one notification of it. This is okay for the present uses.
*/
typedef enum
{
PMSIGNAL_RECOVERY_STARTED, /* recovery has started */
PMSIGNAL_RECOVERY_CONSISTENT, /* recovery has reached consistent state */
PMSIGNAL_BEGIN_HOT_STANDBY, /* begin Hot Standby */
PMSIGNAL_ROTATE_LOGFILE, /* send SIGUSR1 to syslogger to rotate logfile */
PMSIGNAL_START_AUTOVAC_LAUNCHER, /* start an autovacuum launcher */
PMSIGNAL_START_AUTOVAC_WORKER, /* start an autovacuum worker */
PMSIGNAL_IO_WORKER_GROW, /* I/O worker pool wants to grow */
PMSIGNAL_BACKGROUND_WORKER_CHANGE, /* background worker state change */
PMSIGNAL_START_WALRECEIVER, /* start a walreceiver */
PMSIGNAL_ADVANCE_STATE_MACHINE, /* advance postmaster's state machine */
PMSIGNAL_XLOG_IS_SHUTDOWN, /* ShutdownXLOG() completed */
} PMSignalReason;
#define NUM_PMSIGNALS (PMSIGNAL_XLOG_IS_SHUTDOWN+1)
/*
* Reasons why the postmaster would send SIGQUIT to its children.
*/
typedef enum
{
PMQUIT_NOT_SENT = 0, /* postmaster hasn't sent SIGQUIT */
PMQUIT_FOR_CRASH, /* some other backend bought the farm */
PMQUIT_FOR_STOP, /* immediate stop was commanded */
} QuitSignalReason;
/* PMSignalData is an opaque struct, details known only within pmsignal.c */
typedef struct PMSignalData PMSignalData;
#ifdef EXEC_BACKEND
extern PGDLLIMPORT volatile PMSignalData *PMSignalState;
#endif
/*
* prototypes for functions in pmsignal.c
*/
extern void SendPostmasterSignal(PMSignalReason reason);
extern bool CheckPostmasterSignal(PMSignalReason reason);
extern void SetQuitSignalReason(QuitSignalReason reason);
extern QuitSignalReason GetQuitSignalReason(void);
extern void MarkPostmasterChildSlotAssigned(int slot);
extern bool MarkPostmasterChildSlotUnassigned(int slot);
extern bool IsPostmasterChildWalSender(int slot);
extern void RegisterPostmasterChildActive(void);
extern void MarkPostmasterChildWalSender(void);
extern bool PostmasterIsAliveInternal(void);
extern void PostmasterDeathSignalInit(void);
/*
* Do we have a way to ask for a signal on parent death?
*
* If we do, pmsignal.c will set up a signal handler, that sets a flag when
* the parent dies. Checking the flag first makes PostmasterIsAlive() a lot
* cheaper in usual case that the postmaster is alive.
*/
#if (defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_PDEATHSIG)) || \
(defined(HAVE_SYS_PROCCTL_H) && defined(PROC_PDEATHSIG_CTL))
#define USE_POSTMASTER_DEATH_SIGNAL
#endif
#ifdef USE_POSTMASTER_DEATH_SIGNAL
extern PGDLLIMPORT volatile sig_atomic_t postmaster_possibly_dead;
static inline bool
PostmasterIsAlive(void)
{
if (likely(!postmaster_possibly_dead))
return true;
return PostmasterIsAliveInternal();
}
#else
#define PostmasterIsAlive() PostmasterIsAliveInternal()
#endif
#endif /* PMSIGNAL_H */