1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-07 00:36:50 +03:00

Use condition variables to wait for checkpoints.

Previously we used a polling/sleeping loop to wait for checkpoints
to begin and end, which leads to up to a couple hundred milliseconds
of needless thumb-twiddling.  Use condition variables instead.

Author: Thomas Munro
Reviewed-by: Andres Freund
Discussion: https://postgr.es/m/CA%2BhUKGLY7sDe%2Bbg1K%3DbnEzOofGoo4bJHYh9%2BcDCXJepb6DQmLw%40mail.gmail.com
This commit is contained in:
Thomas Munro
2019-03-14 10:25:27 +13:00
parent 5655565c07
commit c6c9474aaf
4 changed files with 34 additions and 5 deletions

View File

@ -126,6 +126,9 @@ typedef struct
int ckpt_flags; /* checkpoint flags, as defined in xlog.h */
ConditionVariable start_cv; /* signaled when ckpt_started advances */
ConditionVariable done_cv; /* signaled when ckpt_done advances */
uint32 num_backend_writes; /* counts user backend buffer writes */
uint32 num_backend_fsync; /* counts user backend fsync calls */
@ -428,6 +431,8 @@ CheckpointerMain(void)
CheckpointerShmem->ckpt_started++;
SpinLockRelease(&CheckpointerShmem->ckpt_lck);
ConditionVariableBroadcast(&CheckpointerShmem->start_cv);
/*
* The end-of-recovery checkpoint is a real checkpoint that's
* performed while we're still in recovery.
@ -488,6 +493,8 @@ CheckpointerMain(void)
CheckpointerShmem->ckpt_done = CheckpointerShmem->ckpt_started;
SpinLockRelease(&CheckpointerShmem->ckpt_lck);
ConditionVariableBroadcast(&CheckpointerShmem->done_cv);
if (ckpt_performed)
{
/*
@ -915,6 +922,8 @@ CheckpointerShmemInit(void)
MemSet(CheckpointerShmem, 0, size);
SpinLockInit(&CheckpointerShmem->ckpt_lck);
CheckpointerShmem->max_requests = NBuffers;
ConditionVariableInit(&CheckpointerShmem->start_cv);
ConditionVariableInit(&CheckpointerShmem->done_cv);
}
}
@ -1023,6 +1032,7 @@ RequestCheckpoint(int flags)
new_failed;
/* Wait for a new checkpoint to start. */
ConditionVariablePrepareToSleep(&CheckpointerShmem->start_cv);
for (;;)
{
SpinLockAcquire(&CheckpointerShmem->ckpt_lck);
@ -1032,13 +1042,15 @@ RequestCheckpoint(int flags)
if (new_started != old_started)
break;
CHECK_FOR_INTERRUPTS();
pg_usleep(100000L);
ConditionVariableSleep(&CheckpointerShmem->start_cv,
WAIT_EVENT_CHECKPOINT_START);
}
ConditionVariableCancelSleep();
/*
* We are waiting for ckpt_done >= new_started, in a modulo sense.
*/
ConditionVariablePrepareToSleep(&CheckpointerShmem->done_cv);
for (;;)
{
int new_done;
@ -1051,9 +1063,10 @@ RequestCheckpoint(int flags)
if (new_done - new_started >= 0)
break;
CHECK_FOR_INTERRUPTS();
pg_usleep(100000L);
ConditionVariableSleep(&CheckpointerShmem->done_cv,
WAIT_EVENT_CHECKPOINT_DONE);
}
ConditionVariableCancelSleep();
if (new_failed != old_failed)
ereport(ERROR,

View File

@ -3623,6 +3623,12 @@ pgstat_get_wait_ipc(WaitEventIPC w)
case WAIT_EVENT_BTREE_PAGE:
event_name = "BtreePage";
break;
case WAIT_EVENT_CHECKPOINT_DONE:
event_name = "CheckpointDone";
break;
case WAIT_EVENT_CHECKPOINT_START:
event_name = "CheckpointStart";
break;
case WAIT_EVENT_CLOG_GROUP_UPDATE:
event_name = "ClogGroupUpdate";
break;