<entry>Waiting while sending synchronization requests to the
checkpointer, because the request queue is full.</entry>
</row>
+ <row>
+ <entry><literal>SpinDelay</literal></entry>
+ <entry>Waiting while acquiring a contended spinlock.</entry>
+ </row>
<row>
<entry><literal>VacuumDelay</literal></entry>
<entry>Waiting in a cost-based vacuum delay point.</entry>
#include "common/pg_prng.h"
#include "port/atomics.h"
#include "storage/s_lock.h"
+#include "utils/wait_event.h"
#define MIN_SPINS_PER_DELAY 10
#define MAX_SPINS_PER_DELAY 1000
if (status->cur_delay == 0) /* first time to delay? */
status->cur_delay = MIN_DELAY_USEC;
+ /*
+ * Once we start sleeping, the overhead of reporting a wait event is
+ * justified. Actively spinning easily stands out in profilers, but
+ * sleeping with an exponential backoff is harder to spot...
+ *
+ * We might want to report something more granular at some point, but
+ * this is better than nothing.
+ */
+ pgstat_report_wait_start(WAIT_EVENT_SPIN_DELAY);
pg_usleep(status->cur_delay);
+ pgstat_report_wait_end();
#if defined(S_LOCK_TEST)
fprintf(stdout, "*");
case WAIT_EVENT_REGISTER_SYNC_REQUEST:
event_name = "RegisterSyncRequest";
break;
+ case WAIT_EVENT_SPIN_DELAY:
+ event_name = "SpinDelay";
+ break;
case WAIT_EVENT_VACUUM_DELAY:
event_name = "VacuumDelay";
break;
WAIT_EVENT_RECOVERY_APPLY_DELAY,
WAIT_EVENT_RECOVERY_RETRIEVE_RETRY_INTERVAL,
WAIT_EVENT_REGISTER_SYNC_REQUEST,
+ WAIT_EVENT_SPIN_DELAY,
WAIT_EVENT_VACUUM_DELAY,
WAIT_EVENT_VACUUM_TRUNCATE
} WaitEventTimeout;