At Fri, 28 Apr 2023 11:15:51 +0900 (JST), Kyotaro Horiguchi 
<horikyota....@gmail.com> wrote in 
> At Thu, 27 Apr 2023 17:30:40 -0400, Melanie Plageman 
> <melanieplage...@gmail.com> wrote in 
> > After a quick example implementation of this, I found that it seemed to
> > try and flush the stats less often on an idle standby (good) than using
> > enable_timeout_every().
> 
> Just rearming with the full-interval will work that way. Our existing
> strategy for this is seen in PostgresMain().
> 
>    stats_timeout = pgstat_report_stat(false);
>    if (stats_timeout > 0)
>    {
>       if (!get_timeout_active(BLAH_TIMEOUT))
>           enable_timeout_after(BLAH_TIMEOUT, stats_timeout);
>    }
>    else
>    {
>        if (get_timeout_active(BLAH_TIMEOUT))
>            disable_timeout(BLAH_TIMEOUT, false);
>    }
>    WaitLatch();

Im my example, I left out idle-time flushing, but I realized we don't
need the timeout mechanism here since we're already managing it. So
the following should work (assuming the timestamp updates with
GetCurrentTimestamp() in my last patch).

@@ -3889,13 +3900,23 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool 
randAccess,
                                        /* Update pg_stat_recovery_prefetch 
before sleeping. */
                                        
XLogPrefetcherComputeStats(xlogprefetcher);
 
+                                       /*
+                                        * Report stats; if not time yet, set 
next WaitLatch to
+                                        * wake up at the next reporing time.
+                                        */
+                                       wait_time = pgstat_report_stat(false);
+
+                                       /* if no pending stats, sleep forever */
+                                       if (wait_time == 0)
+                                               wait_time = -1L;
+
                                        /*
                                         * Wait for more WAL to arrive, when we 
will be woken
                                         * immediately by the WAL receiver.
                                         */
                                        (void) 
WaitLatch(&XLogRecoveryCtl->recoveryWakeupLatch,
                                                                         
WL_LATCH_SET | WL_EXIT_ON_PM_DEATH,
-                                                                        -1L,
+                                                                        
wait_time,
                                                                         
WAIT_EVENT_RECOVERY_WAL_STREAM);

regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
diff --git a/src/backend/access/transam/xlogrecovery.c 
b/src/backend/access/transam/xlogrecovery.c
index 188f6d6f85..0dd465c5e3 100644
--- a/src/backend/access/transam/xlogrecovery.c
+++ b/src/backend/access/transam/xlogrecovery.c
@@ -3248,6 +3248,7 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr 
targetPagePtr, int reqLen,
                close(readFile);
                readFile = -1;
                readSource = XLOG_FROM_ANY;
+               pgstat_report_stat(false);
        }
 
        XLByteToSeg(targetPagePtr, readSegNo, wal_segment_size);
@@ -3607,6 +3608,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool 
randAccess,
                                                                                
                        wal_retrieve_retry_interval))
                                        {
                                                long            wait_time;
+                                               long            stats_timeout;
 
                                                wait_time = 
wal_retrieve_retry_interval -
                                                        
TimestampDifferenceMilliseconds(last_fail_time, now);
@@ -3617,6 +3619,14 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool 
randAccess,
                                                /* Do background tasks that 
might benefit us later. */
                                                
KnownAssignedTransactionIdsIdleMaintenance();
 
+                                               /*
+                                                * Report stats; if not time 
yet, set next WaitLatch to
+                                                * wake up at the next reporing 
time.
+                                                */
+                                               stats_timeout = 
pgstat_report_stat(false);
+                                               if (stats_timeout > 0 && 
stats_timeout < wait_time)
+                                                       wait_time = 
stats_timeout;
+
                                                (void) 
WaitLatch(&XLogRecoveryCtl->recoveryWakeupLatch,
                                                                                
 WL_LATCH_SET | WL_TIMEOUT |
                                                                                
 WL_EXIT_ON_PM_DEATH,
@@ -3698,6 +3708,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool 
randAccess,
                        case XLOG_FROM_STREAM:
                                {
                                        bool            havedata;
+                                       long            wait_time;
 
                                        /*
                                         * We should be able to move to 
XLOG_FROM_STREAM only in
@@ -3889,13 +3900,23 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool 
randAccess,
                                        /* Update pg_stat_recovery_prefetch 
before sleeping. */
                                        
XLogPrefetcherComputeStats(xlogprefetcher);
 
+                                       /*
+                                        * Report stats; if not time yet, set 
next WaitLatch to
+                                        * wake up at the next reporing time.
+                                        */
+                                       wait_time = pgstat_report_stat(false);
+
+                                       /* if no pending stats, sleep forever */
+                                       if (wait_time == 0)
+                                               wait_time = -1L;
+
                                        /*
                                         * Wait for more WAL to arrive, when we 
will be woken
                                         * immediately by the WAL receiver.
                                         */
                                        (void) 
WaitLatch(&XLogRecoveryCtl->recoveryWakeupLatch,
                                                                         
WL_LATCH_SET | WL_EXIT_ON_PM_DEATH,
-                                                                        -1L,
+                                                                        
wait_time,
                                                                         
WAIT_EVENT_RECOVERY_WAL_STREAM);
                                        
ResetLatch(&XLogRecoveryCtl->recoveryWakeupLatch);
                                        break;
diff --git a/src/backend/storage/buffer/bufmgr.c 
b/src/backend/storage/buffer/bufmgr.c
index 1fa689052e..520936d0dd 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -1046,9 +1046,6 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, 
ForkNumber forkNum,
                bufHdr = LocalBufferAlloc(smgr, forkNum, blockNum, &found);
                if (found)
                        pgBufferUsage.local_blks_hit++;
-               else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-                                mode == RBM_ZERO_ON_ERROR)
-                       pgBufferUsage.local_blks_read++;
        }
        else
        {
@@ -1062,9 +1059,6 @@ ReadBuffer_common(SMgrRelation smgr, char relpersistence, 
ForkNumber forkNum,
                                                         strategy, &found, 
io_context);
                if (found)
                        pgBufferUsage.shared_blks_hit++;
-               else if (mode == RBM_NORMAL || mode == RBM_NORMAL_NO_LOG ||
-                                mode == RBM_ZERO_ON_ERROR)
-                       pgBufferUsage.shared_blks_read++;
        }
 
        /* At this point we do NOT hold any locks. */
@@ -1126,6 +1120,10 @@ ReadBuffer_common(SMgrRelation smgr, char 
relpersistence, ForkNumber forkNum,
 
                pgstat_count_io_op_time(io_object, io_context,
                                                                IOOP_READ, 
io_start, 1);
+               if (isLocalBuf)
+                       pgBufferUsage.local_blks_read++;
+               else
+                       pgBufferUsage.shared_blks_read++;
 
                /* check for garbage data */
                if (!PageIsVerifiedExtended((Page) bufBlock, blockNum,
diff --git a/src/backend/utils/activity/pgstat.c 
b/src/backend/utils/activity/pgstat.c
index b125802b21..0864b56689 100644
--- a/src/backend/utils/activity/pgstat.c
+++ b/src/backend/utils/activity/pgstat.c
@@ -608,7 +608,10 @@ pgstat_report_stat(bool force)
         */
        Assert(!pgStatLocal.shmem->is_shutdown);
 
-       now = GetCurrentTransactionStopTimestamp();
+       if (MyBackendType != B_STARTUP)
+               now = GetCurrentTransactionStopTimestamp();
+       else
+               now = GetCurrentTimestamp();
 
        if (!force)
        {
diff --git a/src/backend/utils/activity/pgstat_database.c 
b/src/backend/utils/activity/pgstat_database.c
index 7149f22f72..c93b92771a 100644
--- a/src/backend/utils/activity/pgstat_database.c
+++ b/src/backend/utils/activity/pgstat_database.c
@@ -17,6 +17,7 @@
 
 #include "postgres.h"
 
+#include "executor/instrument.h"
 #include "utils/pgstat_internal.h"
 #include "utils/timestamp.h"
 #include "storage/procsignal.h"
@@ -269,7 +270,10 @@ AtEOXact_PgStat_Database(bool isCommit, bool parallel)
 void
 pgstat_update_dbstats(TimestampTz ts)
 {
+       static BufferUsage lastBufferUsage = {0};
        PgStat_StatDBEntry *dbentry;
+       PgStat_Counter hit_diff;
+       PgStat_Counter read_diff;
 
        dbentry = pgstat_prep_database_pending(MyDatabaseId);
 
@@ -282,6 +286,16 @@ pgstat_update_dbstats(TimestampTz ts)
        dbentry->blk_read_time += pgStatBlockReadTime;
        dbentry->blk_write_time += pgStatBlockWriteTime;
 
+       /* we need to preserve pgBufferUsage */
+       read_diff =
+               pgBufferUsage.shared_blks_read - 
lastBufferUsage.shared_blks_read +
+               pgBufferUsage.local_blks_read - lastBufferUsage.local_blks_read;
+       hit_diff = 
+               pgBufferUsage.shared_blks_hit - lastBufferUsage.shared_blks_hit 
+
+               pgBufferUsage.local_blks_hit - lastBufferUsage.local_blks_hit;
+       dbentry->blocks_fetched += read_diff + hit_diff;
+       dbentry->blocks_hit += hit_diff;
+
        if (pgstat_should_report_connstat())
        {
                long            secs;
@@ -304,6 +318,8 @@ pgstat_update_dbstats(TimestampTz ts)
        pgStatBlockWriteTime = 0;
        pgStatActiveTime = 0;
        pgStatTransactionIdleTime = 0;
+
+       lastBufferUsage = pgBufferUsage;
 }
 
 /*
diff --git a/src/backend/utils/activity/pgstat_relation.c 
b/src/backend/utils/activity/pgstat_relation.c
index 9876e0c1e8..8945b8141a 100644
--- a/src/backend/utils/activity/pgstat_relation.c
+++ b/src/backend/utils/activity/pgstat_relation.c
@@ -844,8 +844,6 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool 
nowait)
        dbentry->tuples_inserted += lstats->counts.tuples_inserted;
        dbentry->tuples_updated += lstats->counts.tuples_updated;
        dbentry->tuples_deleted += lstats->counts.tuples_deleted;
-       dbentry->blocks_fetched += lstats->counts.blocks_fetched;
-       dbentry->blocks_hit += lstats->counts.blocks_hit;
 
        return true;
 }

Reply via email to