checkpoint-stats-update.diff

text/plain

Filename: checkpoint-stats-update.diff
Type: text/plain
Part: 0
Message: PATCH: regular logging of checkpoint progress
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 ----
        </listitem>
       </varlistentry>
  
+      <varlistentry id="guc-checkpoint-update-limit" xreflabel="checkpoint_update_limit">
+       <term><varname>checkpoint_update_limit</varname> (<type>integer</type>)</term>
+       <indexterm>
+        <primary><varname>checkpoint_update_limit</> configuration parameter</primary>
+       </indexterm>
+       <listitem>
+        <para>
+         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 <filename>postgresql.conf</> file or on the server command line.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
       </variablelist>
       </sect2>
       <sect2 id="runtime-config-wal-archiving">
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;