Skip to content

Commit e2a82cd

Browse files
committed
Flush the IO statistics of active WAL senders more frequently
WAL senders do not flush their statistics until they exit, limiting the monitoring possible for live processes. This is penalizing when WAL senders are running for a long time, like in streaming or logical replication setups, because it is not possible to know the amount of IO they generate while running. This commit makes WAL senders more aggressive with their statistics flush, using an internal of 1 second, with the flush timing calculated based on the existing GetCurrentTimestamp() done before the sleeps done to wait for some activity. Note that the sleep done for logical and physical WAL senders happens in two different code paths, so the stats flushes need to happen in these two places. One test is added for the physical WAL sender case, and one for the logical WAL sender case. This can be done in a stable fashion by relying on the WAL generated by the TAP tests in combination with a stats reset while a server is running, but only on HEAD as WAL data has been added to pg_stat_io in a051e71. This issue exists since a9c70b4 and the introduction of pg_stat_io, so backpatch down to v16. Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com> Reviewed-by: vignesh C <vignesh21@gmail.com> Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com> Discussion: https://postgr.es/m/Z73IsKBceoVd4t55@ip-10-97-1-34.eu-west-3.compute.internal Backpatch-through: 16
1 parent 00f0bb4 commit e2a82cd

File tree

1 file changed

+32
-3
lines changed

1 file changed

+32
-3
lines changed

src/backend/replication/walsender.c

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,14 @@
9090
#include "utils/guc.h"
9191
#include "utils/memutils.h"
9292
#include "utils/pg_lsn.h"
93-
#include "utils/portal.h"
93+
#include "utils/pgstat_internal.h"
9494
#include "utils/ps_status.h"
9595
#include "utils/timeout.h"
9696
#include "utils/timestamp.h"
9797

98+
/* Minimum interval used by walsender for stats flushes, in ms */
99+
#define WALSENDER_STATS_FLUSH_INTERVAL 1000
100+
98101
/*
99102
* Maximum data payload in a WAL data message. Must be >= XLOG_BLCKSZ.
100103
*
@@ -1540,6 +1543,7 @@ WalSndWaitForWal(XLogRecPtr loc)
15401543
{
15411544
int wakeEvents;
15421545
static XLogRecPtr RecentFlushPtr = InvalidXLogRecPtr;
1546+
TimestampTz last_flush = 0;
15431547

15441548
/*
15451549
* Fast path to avoid acquiring the spinlock in case we already know we
@@ -1559,6 +1563,7 @@ WalSndWaitForWal(XLogRecPtr loc)
15591563
for (;;)
15601564
{
15611565
long sleeptime;
1566+
TimestampTz now;
15621567

15631568
/* Clear any already-pending wakeups */
15641569
ResetLatch(MyLatch);
@@ -1648,13 +1653,22 @@ WalSndWaitForWal(XLogRecPtr loc)
16481653
* new WAL to be generated. (But if we have nothing to send, we don't
16491654
* want to wake on socket-writable.)
16501655
*/
1651-
sleeptime = WalSndComputeSleeptime(GetCurrentTimestamp());
1656+
now = GetCurrentTimestamp();
1657+
sleeptime = WalSndComputeSleeptime(now);
16521658

16531659
wakeEvents = WL_SOCKET_READABLE;
16541660

16551661
if (pq_is_send_pending())
16561662
wakeEvents |= WL_SOCKET_WRITEABLE;
16571663

1664+
/* Report IO statistics, if needed */
1665+
if (TimestampDifferenceExceeds(last_flush, now,
1666+
WALSENDER_STATS_FLUSH_INTERVAL))
1667+
{
1668+
pgstat_flush_io(false);
1669+
last_flush = now;
1670+
}
1671+
16581672
WalSndWait(wakeEvents, sleeptime, WAIT_EVENT_WAL_SENDER_WAIT_WAL);
16591673
}
16601674

@@ -2446,6 +2460,8 @@ WalSndCheckTimeOut(void)
24462460
static void
24472461
WalSndLoop(WalSndSendDataCallback send_data)
24482462
{
2463+
TimestampTz last_flush = 0;
2464+
24492465
/*
24502466
* Initialize the last reply timestamp. That enables timeout processing
24512467
* from hereon.
@@ -2540,13 +2556,17 @@ WalSndLoop(WalSndSendDataCallback send_data)
25402556
* WalSndWaitForWal() handle any other blocking; idle receivers need
25412557
* its additional actions. For physical replication, also block if
25422558
* caught up; its send_data does not block.
2559+
*
2560+
* The IO statistics are reported in WalSndWaitForWal() for the
2561+
* logical WAL senders.
25432562
*/
25442563
if ((WalSndCaughtUp && send_data != XLogSendLogical &&
25452564
!streamingDoneSending) ||
25462565
pq_is_send_pending())
25472566
{
25482567
long sleeptime;
25492568
int wakeEvents;
2569+
TimestampTz now;
25502570

25512571
if (!streamingDoneReceiving)
25522572
wakeEvents = WL_SOCKET_READABLE;
@@ -2557,11 +2577,20 @@ WalSndLoop(WalSndSendDataCallback send_data)
25572577
* Use fresh timestamp, not last_processing, to reduce the chance
25582578
* of reaching wal_sender_timeout before sending a keepalive.
25592579
*/
2560-
sleeptime = WalSndComputeSleeptime(GetCurrentTimestamp());
2580+
now = GetCurrentTimestamp();
2581+
sleeptime = WalSndComputeSleeptime(now);
25612582

25622583
if (pq_is_send_pending())
25632584
wakeEvents |= WL_SOCKET_WRITEABLE;
25642585

2586+
/* Report IO statistics, if needed */
2587+
if (TimestampDifferenceExceeds(last_flush, now,
2588+
WALSENDER_STATS_FLUSH_INTERVAL))
2589+
{
2590+
pgstat_flush_io(false);
2591+
last_flush = now;
2592+
}
2593+
25652594
/* Sleep until something happens or we time out */
25662595
WalSndWait(wakeEvents, sleeptime, WAIT_EVENT_WAL_SENDER_MAIN);
25672596
}

0 commit comments

Comments
 (0)