diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
new file mode 100644
index 67e722f..64d84b0
*** a/doc/src/sgml/config.sgml
--- b/doc/src/sgml/config.sgml
*************** SET ENABLE_SEQSCAN TO OFF;
*** 1863,1868 ****
--- 1863,1885 ----
+
+ checkpoint_update_limit (integer)
+
+ checkpoint_update_limit> configuration parameter
+
+
+
+ Number of buffers written during a checkpoint between logging a status
+ (with total number of buffers to write, number of already written buffers,
+ average/current write and estimate of the remaining time) and updates bgwriter
+ stats at the same time. The default value 0 disables the continuous updates so
+ the stats are updated only at the end of the checkpoint. This parameter can only
+ be set in the postgresql.conf> file or on the server command line.
+
+
+
+
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
new file mode 100644
index 4c7cfb0..b24ec93
*** a/src/backend/storage/buffer/bufmgr.c
--- b/src/backend/storage/buffer/bufmgr.c
***************
*** 66,71 ****
--- 66,72 ----
bool zero_damaged_pages = false;
int bgwriter_lru_maxpages = 100;
double bgwriter_lru_multiplier = 2.0;
+ int checkpoint_update_limit = 0;
/*
* How many buffers PrefetchBuffer callers should try to stay ahead of their
*************** BufferSync(int flags)
*** 1175,1180 ****
--- 1176,1192 ----
int num_to_write;
int num_written;
int mask = BM_DIRTY;
+
+ int num_since_update;
+
+ long curr_secs,
+ total_secs;
+ int curr_usecs,
+ total_usecs;
+ float curr_time,
+ total_time;
+
+ TimestampTz startTimestamp, lastTimestamp;
/* Make sure we can handle the pin inside SyncOneBuffer */
ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
*************** BufferSync(int flags)
*** 1238,1243 ****
--- 1250,1260 ----
buf_id = StrategySyncStart(NULL, NULL);
num_to_scan = NBuffers;
num_written = 0;
+ num_since_update = 0;
+
+ startTimestamp = GetCurrentTimestamp();
+ lastTimestamp = startTimestamp;
+
while (num_to_scan-- > 0)
{
volatile BufferDesc *bufHdr = &BufferDescriptors[buf_id];
*************** BufferSync(int flags)
*** 1261,1266 ****
--- 1278,1327 ----
TRACE_POSTGRESQL_BUFFER_SYNC_WRITTEN(buf_id);
BgWriterStats.m_buf_written_checkpoints++;
num_written++;
+ num_since_update++;
+
+ /*
+ * Every time we write enough buffers (checkpoint_update_limit),
+ * we log a checkpoint status message and update the bgwriter
+ * stats (so that the pg_stat_bgwriter table may be updated).
+ *
+ * The log message contains info about total number of buffers to
+ * write, how many buffers are already written, average and current
+ * write speed and an estimate remaining time.
+ */
+ if ((checkpoint_update_limit > 0) && (num_since_update >= checkpoint_update_limit))
+ {
+
+ TimestampDifference(lastTimestamp,
+ GetCurrentTimestamp(),
+ &curr_secs, &curr_usecs);
+
+ TimestampDifference(startTimestamp,
+ GetCurrentTimestamp(),
+ &total_secs, &total_usecs);
+
+ curr_time = curr_secs + (float)curr_usecs / 1000000;
+ total_time = total_secs + (float)total_usecs / 1000000;
+
+ elog(LOG, "checkpoint status: wrote %d buffers of %d (%.1f%%) in %.1f s; "
+ "average %.1f MB/s (%d buffers, %ld.%03d s), "
+ "current %.1f MB/s (%d buffers, %ld.%03d s), "
+ "remaining %.1f s",
+ num_written, num_to_write, ((float) num_written * 100 / num_to_write),
+ total_time,
+ ((float)BLCKSZ * num_written / 1024 / 1024 / total_time),
+ num_written, total_secs, total_usecs/1000,
+ ((float)BLCKSZ * num_since_update / 1024 / 1024 / curr_time),
+ num_since_update, curr_secs, curr_usecs/1000,
+ (float)(num_to_write - num_written) * total_time / (num_written));
+
+ pgstat_send_bgwriter();
+
+ /* reset the counter and timestamp */
+ num_since_update = 0;
+ lastTimestamp = GetCurrentTimestamp();
+
+ }
/*
* We know there are at most num_to_write buffers with
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
new file mode 100644
index 6670997..2176933
*** a/src/backend/utils/misc/guc.c
--- b/src/backend/utils/misc/guc.c
*************** static struct config_int ConfigureNamesI
*** 1965,1970 ****
--- 1965,1981 ----
},
{
+ {"checkpoint_update_limit", PGC_SIGHUP, WAL_CHECKPOINTS,
+ gettext_noop("Sets number of buffers written between stats updates during a checkpoint."),
+ gettext_noop("Every time the checkpoint writes this number of buffers, it updates "
+ "the stats in pg_stat_bgwriter and logs a message with the current checkpoint progress. "
+ "Zero means the stats are updated when the checkpoint only."),
+ },
+ &checkpoint_update_limit,
+ 0, 0, INT_MAX, NULL, NULL
+ },
+
+ {
{"wal_buffers", PGC_POSTMASTER, WAL_SETTINGS,
gettext_noop("Sets the number of disk-page buffers in shared memory for WAL."),
NULL,
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
new file mode 100644
index 65fd126..284ddd1
*** a/src/backend/utils/misc/postgresql.conf.sample
--- b/src/backend/utils/misc/postgresql.conf.sample
***************
*** 180,185 ****
--- 180,187 ----
#checkpoint_timeout = 5min # range 30s-1h
#checkpoint_completion_target = 0.5 # checkpoint target duration, 0.0 - 1.0
#checkpoint_warning = 30s # 0 disables
+ #checkpoint_update_limit = 0 # buffers written between loggin checkpoint
+ # status and updating bgwriter stats, 0 disables
# - Archiving -
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
new file mode 100644
index b8fc87e..b36a87a
*** a/src/include/storage/bufmgr.h
--- b/src/include/storage/bufmgr.h
*************** extern bool zero_damaged_pages;
*** 49,54 ****
--- 49,55 ----
extern int bgwriter_lru_maxpages;
extern double bgwriter_lru_multiplier;
extern int target_prefetch_pages;
+ extern int checkpoint_update_limit;
/* in buf_init.c */
extern PGDLLIMPORT char *BufferBlocks;