From 7dde0761bc16fa20e2c3930e0759cd1acb1ae770 Mon Sep 17 00:00:00 2001 From: Jakub Wartak Date: Fri, 24 Jul 2026 08:30:20 +0200 Subject: [PATCH v22092026 03/11] pg_basebackup: report average data transfer throughput in verbose mode Add the average data transfer rate to the "base backup completed" message. The transfer is timed with instr_time from just before the archive data is received until all data has arrived (but before fsync is called) Author: Jakub Wartak Discussion: --- src/bin/pg_basebackup/pg_basebackup.c | 31 ++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c index 4628900da10..b6e469d47bb 100644 --- a/src/bin/pg_basebackup/pg_basebackup.c +++ b/src/bin/pg_basebackup/pg_basebackup.c @@ -37,6 +37,7 @@ #include "fe_utils/recovery_gen.h" #include "getopt_long.h" #include "libpq/protocol.h" +#include "portability/instr_time.h" #include "receivelog.h" #include "streamutil.h" @@ -1790,6 +1791,8 @@ BaseBackup(char *compression_algorithm, char *compression_detail, int writing_to_stdout; bool use_new_option_syntax = false; PQExpBufferData buf; + instr_time transfer_start; + instr_time transfer_elapsed; Assert(conn != NULL); initPQExpBuffer(&buf); @@ -2145,6 +2148,9 @@ BaseBackup(char *compression_algorithm, char *compression_detail, wal_compress_level); } + /* Start timing the data transfer, for the average rate report. */ + INSTR_TIME_SET_CURRENT(transfer_start); + if (serverMajor >= 1500) { /* Receive a single tar stream with everything. */ @@ -2197,6 +2203,13 @@ BaseBackup(char *compression_algorithm, char *compression_detail, ReceiveBackupManifest(conn); } + /* + * All backup data has been received, so measure how long the transfer + * took for the average rate report shown at completion. + */ + INSTR_TIME_SET_CURRENT(transfer_elapsed); + INSTR_TIME_SUBTRACT(transfer_elapsed, transfer_start); + if (showprogress) { progress_update_filename(NULL); @@ -2365,7 +2378,22 @@ BaseBackup(char *compression_algorithm, char *compression_detail, } if (verbose) - pg_log_info("base backup completed"); + { + double elapsed_sec = INSTR_TIME_GET_DOUBLE(transfer_elapsed); + + /* + * Avoids potential division by zero. + * + * Timing does not include potential fsync()/syncfs(), so data might be + * still in-flight from pagecache when total_done was calculated, therefore + * we make it clear to the user what we are measuring. + */ + if (elapsed_sec > 0.0) + pg_log_info("base backup completed (avg %.1f MB/s)", + (double) totaldone / (1024 * 1024) / elapsed_sec); + else + pg_log_info("base backup completed"); + } } @@ -2422,6 +2450,7 @@ main(int argc, char **argv) pg_logging_init(argv[0]); progname = get_progname(argv[0]); set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_basebackup")); + pg_initialize_timing(); if (argc > 1) { -- 2.43.5