From 6c11de18f460232f7064a56aff3413406c824ff3 Mon Sep 17 00:00:00 2001 From: Maxim Orlov Date: Thu, 27 Feb 2025 12:59:51 +0300 Subject: [PATCH v1] AbsorbSyncRequests incrementally, instead of doing it for all requests at once. --- src/backend/postmaster/checkpointer.c | 59 +++++++++++++++++---------- 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 7acbbd3e267..a4c6544e13b 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -1321,42 +1321,57 @@ CompactCheckpointerRequestQueue(void) void AbsorbSyncRequests(void) { - CheckpointerRequest *requests = NULL; - CheckpointerRequest *request; - int n; + CheckpointerRequest *requests = NULL; + int num_requests, + max_requests; if (!AmCheckpointerProcess()) return; LWLockAcquire(CheckpointerCommLock, LW_EXCLUSIVE); + num_requests = CheckpointerShmem->num_requests; /* - * We try to avoid holding the lock for a long time by copying the request - * array, and processing the requests after releasing the lock. - * - * Once we have cleared the requests from shared memory, we have to PANIC - * if we then fail to absorb them (eg, because our hashtable runs out of - * memory). This is because the system cannot run safely if we are unable - * to fsync what we have been told to fsync. Fortunately, the hashtable - * is so small that the problem is quite unlikely to arise in practice. + * Note: this can be chosen arbitrarily, stick for 1Gb for now. */ - n = CheckpointerShmem->num_requests; - if (n > 0) + max_requests = MaxAllocSize / sizeof(CheckpointerRequest); + + for (int i = 0; i < num_requests; i += max_requests) { - requests = (CheckpointerRequest *) palloc(n * sizeof(CheckpointerRequest)); - memcpy(requests, CheckpointerShmem->requests, n * sizeof(CheckpointerRequest)); - } + Size n = (num_requests - i >= max_requests) ? max_requests : + num_requests - i; - START_CRIT_SECTION(); + if (!requests) + requests = palloc(n * sizeof(CheckpointerRequest)); - CheckpointerShmem->num_requests = 0; + memcpy(requests, CheckpointerShmem->requests + i, + n * sizeof(CheckpointerRequest)); - LWLockRelease(CheckpointerCommLock); + LWLockRelease(CheckpointerCommLock); + + START_CRIT_SECTION(); - for (request = requests; n > 0; request++, n--) - RememberSyncRequest(&request->ftag, request->type); + /* + * We try to avoid holding the lock for a long time by copying the + * request array, and processing the requests after releasing the lock. + * + * Once we have cleared the requests from shared memory, we have to + * PANIC if we then fail to absorb them (eg, because our hashtable runs + * out of memory). This is because the system cannot run safely if we + * are unable to fsync what we have been told to fsync. Fortunately, + * the hashtable is so small that the problem is quite unlikely to arise + * in practice. + */ + for (int j = 0; j < n; j++) + RememberSyncRequest(&requests[j].ftag, requests[j].type); + + END_CRIT_SECTION(); - END_CRIT_SECTION(); + LWLockAcquire(CheckpointerCommLock, LW_EXCLUSIVE); + } + + CheckpointerShmem->num_requests = 0; + LWLockRelease(CheckpointerCommLock); if (requests) pfree(requests); -- 2.43.0