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;