sync-spread-v2.patch
text/x-patch
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v2
| File | + | − |
|---|---|---|
| src/backend/postmaster/bgwriter.c | 86 | 15 |
| src/backend/storage/smgr/md.c | 5 | 19 |
| src/include/postmaster/bgwriter.h | 2 | 1 |
diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c
index 43a149e..0ce8e2b 100644
--- a/src/backend/postmaster/bgwriter.c
+++ b/src/backend/postmaster/bgwriter.c
@@ -143,8 +143,8 @@ typedef struct
static BgWriterShmemStruct *BgWriterShmem;
-/* interval for calling AbsorbFsyncRequests in CheckpointWriteDelay */
-#define WRITES_PER_ABSORB 1000
+/* Fraction of fsync absorb queue that needs to be filled before acting */
+#define ABSORB_ACTION_DIVISOR 10
/*
* GUC parameters
@@ -382,7 +382,7 @@ BackgroundWriterMain(void)
/*
* Process any requests or signals received recently.
*/
- AbsorbFsyncRequests();
+ AbsorbFsyncRequests(false);
if (got_SIGHUP)
{
@@ -636,7 +636,7 @@ BgWriterNap(void)
(ckpt_active ? ImmediateCheckpointRequested() : checkpoint_requested))
break;
pg_usleep(1000000L);
- AbsorbFsyncRequests();
+ AbsorbFsyncRequests(true);
udelay -= 1000000L;
}
@@ -684,8 +684,6 @@ ImmediateCheckpointRequested(void)
void
CheckpointWriteDelay(int flags, double progress)
{
- static int absorb_counter = WRITES_PER_ABSORB;
-
/* Do nothing if checkpoint is being executed by non-bgwriter process */
if (!am_bg_writer)
return;
@@ -705,22 +703,65 @@ CheckpointWriteDelay(int flags, double progress)
ProcessConfigFile(PGC_SIGHUP);
}
- AbsorbFsyncRequests();
- absorb_counter = WRITES_PER_ABSORB;
+ AbsorbFsyncRequests(false);
BgBufferSync();
CheckArchiveTimeout();
BgWriterNap();
}
- else if (--absorb_counter <= 0)
+ else
{
/*
- * Absorb pending fsync requests after each WRITES_PER_ABSORB write
- * operations even when we don't sleep, to prevent overflow of the
- * fsync request queue.
+ * Check for overflow of the fsync request queue.
*/
- AbsorbFsyncRequests();
- absorb_counter = WRITES_PER_ABSORB;
+ AbsorbFsyncRequests(false);
+ }
+}
+
+/*
+ * CheckpointSyncDelay -- yield control to bgwriter during a checkpoint
+ *
+ * This function is called after each file sync performed by mdsync().
+ * It is responsible for keeping the bgwriter's normal activities in
+ * progress during a long checkpoint.
+ */
+void
+CheckpointSyncDelay(void)
+{
+ pg_time_t now;
+ pg_time_t sync_start_time;
+ int sync_delay_secs;
+
+ /*
+ * Delay after each sync, in seconds. This could be a parameter. But
+ * since ideally this will be auto-tuning in the near future, not
+ * assigning it a GUC setting yet.
+ */
+#define EXTRA_SYNC_DELAY 3
+
+ /* Do nothing if checkpoint is being executed by non-bgwriter process */
+ if (!am_bg_writer)
+ return;
+
+ sync_start_time = (pg_time_t) time(NULL);
+
+ /*
+ * Perform the usual bgwriter duties.
+ */
+ for (;;)
+ {
+ AbsorbFsyncRequests(false);
+ BgBufferSync();
+ CheckArchiveTimeout();
+ BgWriterNap();
+
+ /*
+ * Are we there yet?
+ */
+ now = (pg_time_t) time(NULL);
+ sync_delay_secs = now - sync_start_time;
+ if (sync_delay_secs >= EXTRA_SYNC_DELAY)
+ break;
}
}
@@ -1116,16 +1157,41 @@ ForwardFsyncRequest(RelFileNodeBackend rnode, ForkNumber forknum,
* non-bgwriter processes, do nothing if not bgwriter.
*/
void
-AbsorbFsyncRequests(void)
+AbsorbFsyncRequests(bool force)
{
BgWriterRequest *requests = NULL;
BgWriterRequest *request;
int n;
+ /*
+ * Divide the size of the request queue by this to determine when
+ * absorption action needs to be taken. Default here aims to empty the
+ * queue whenever 1 / 10 = 10% of it is full. If this isn't good enough,
+ * you probably need to lower bgwriter_delay, rather than presume
+ * this needs to be a tunable you can decrease.
+ */
+ int absorb_action_divisor = 10;
+
if (!am_bg_writer)
return;
/*
+ * If the queue isn't very large, don't worry about absorbing yet.
+ * Access integer counter without lock, to avoid queuing.
+ */
+ if (!force && BgWriterShmem->num_requests <
+ (BgWriterShmem->max_requests / ABSORB_ACTION_DIVISOR))
+ {
+ if (BgWriterShmem->num_requests > 0)
+ elog(DEBUG1,"Absorb queue: %d fsync requests, not processing",
+ BgWriterShmem->num_requests);
+ return;
+ }
+
+ elog(DEBUG1,"Absorb queue: %d fsync requests, processing",
+ BgWriterShmem->num_requests);
+
+ /*
* We have to PANIC if we fail to absorb all the pending requests (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
@@ -1167,4 +1233,9 @@ AbsorbFsyncRequests(void)
pfree(requests);
END_CRIT_SECTION();
+
+ /*
+ * Send off activity statistics to the stats collector
+ */
+ pgstat_send_bgwriter();
}
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index 7140b94..57066c4 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -36,9 +36,6 @@
*/
#define DEBUG_FSYNC 1
-/* interval for calling AbsorbFsyncRequests in mdsync */
-#define FSYNCS_PER_ABSORB 10
-
/* special values for the segno arg to RememberFsyncRequest */
#define FORGET_RELATION_FSYNC (InvalidBlockNumber)
#define FORGET_DATABASE_FSYNC (InvalidBlockNumber-1)
@@ -931,7 +928,6 @@ mdsync(void)
HASH_SEQ_STATUS hstat;
PendingOperationEntry *entry;
- int absorb_counter;
#ifdef DEBUG_FSYNC
/* Statistics on sync times */
@@ -958,7 +954,7 @@ mdsync(void)
* queued an fsync request before clearing the buffer's dirtybit, so we
* are safe as long as we do an Absorb after completing BufferSync().
*/
- AbsorbFsyncRequests();
+ AbsorbFsyncRequests(true);
/*
* To avoid excess fsync'ing (in the worst case, maybe a never-terminating
@@ -1001,7 +997,6 @@ mdsync(void)
mdsync_in_progress = true;
/* Now scan the hashtable for fsync requests to process */
- absorb_counter = FSYNCS_PER_ABSORB;
hash_seq_init(&hstat, pendingOpsTable);
while ((entry = (PendingOperationEntry *) hash_seq_search(&hstat)) != NULL)
{
@@ -1026,17 +1021,9 @@ mdsync(void)
int failures;
/*
- * If in bgwriter, we want to absorb pending requests every so
- * often to prevent overflow of the fsync request queue. It is
- * unspecified whether newly-added entries will be visited by
- * hash_seq_search, but we don't care since we don't need to
- * process them anyway.
+ * If in bgwriter, perform normal duties.
*/
- if (--absorb_counter <= 0)
- {
- AbsorbFsyncRequests();
- absorb_counter = FSYNCS_PER_ABSORB;
- }
+ CheckpointSyncDelay();
/*
* The fsync table could contain requests to fsync segments that
@@ -1131,10 +1118,9 @@ mdsync(void)
pfree(path);
/*
- * Absorb incoming requests and check to see if canceled.
+ * If in bgwriter, perform normal duties.
*/
- AbsorbFsyncRequests();
- absorb_counter = FSYNCS_PER_ABSORB; /* might as well... */
+ CheckpointSyncDelay();
if (entry->canceled)
break;
diff --git a/src/include/postmaster/bgwriter.h b/src/include/postmaster/bgwriter.h
index e251da6..4939604 100644
--- a/src/include/postmaster/bgwriter.h
+++ b/src/include/postmaster/bgwriter.h
@@ -26,10 +26,11 @@ extern void BackgroundWriterMain(void);
extern void RequestCheckpoint(int flags);
extern void CheckpointWriteDelay(int flags, double progress);
+extern void CheckpointSyncDelay(void);
extern bool ForwardFsyncRequest(RelFileNodeBackend rnode, ForkNumber forknum,
BlockNumber segno);
-extern void AbsorbFsyncRequests(void);
+extern void AbsorbFsyncRequests(bool force);
extern Size BgWriterShmemSize(void);
extern void BgWriterShmemInit(void);