diff options
-rw-r--r-- | src/backend/access/transam/xlog.c | 4 | ||||
-rw-r--r-- | src/backend/postmaster/checkpointer.c | 26 | ||||
-rw-r--r-- | src/backend/postmaster/pgstat.c | 124 | ||||
-rw-r--r-- | src/backend/storage/buffer/bufmgr.c | 8 | ||||
-rw-r--r-- | src/backend/utils/adt/pgstatfuncs.c | 27 | ||||
-rw-r--r-- | src/include/pgstat.h | 63 |
6 files changed, 185 insertions, 67 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 8b39a2fdaa5..d0ec6a834be 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -8721,8 +8721,8 @@ LogCheckpointEnd(bool restartpoint) CheckpointStats.ckpt_sync_end_t); /* Accumulate checkpoint timing summary data, in milliseconds. */ - BgWriterStats.m_checkpoint_write_time += write_msecs; - BgWriterStats.m_checkpoint_sync_time += sync_msecs; + PendingCheckpointerStats.m_checkpoint_write_time += write_msecs; + PendingCheckpointerStats.m_checkpoint_sync_time += sync_msecs; /* * All of the published timing statistics are accounted for. Only diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index bc9ac7ccfaf..be7366379d0 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -357,7 +357,7 @@ CheckpointerMain(void) if (((volatile CheckpointerShmemStruct *) CheckpointerShmem)->ckpt_flags) { do_checkpoint = true; - BgWriterStats.m_requested_checkpoints++; + PendingCheckpointerStats.m_requested_checkpoints++; } /* @@ -371,7 +371,7 @@ CheckpointerMain(void) if (elapsed_secs >= CheckPointTimeout) { if (!do_checkpoint) - BgWriterStats.m_timed_checkpoints++; + PendingCheckpointerStats.m_timed_checkpoints++; do_checkpoint = true; flags |= CHECKPOINT_CAUSE_TIME; } @@ -493,13 +493,9 @@ CheckpointerMain(void) CheckArchiveTimeout(); /* - * Send off activity statistics to the stats collector. (The reason - * why we re-use bgwriter-related code for this is that the bgwriter - * and checkpointer used to be just one process. It's probably not - * worth the trouble to split the stats support into two independent - * stats message types.) + * Send off activity statistics to the stats collector. */ - pgstat_send_bgwriter(); + pgstat_send_checkpointer(); /* Send WAL statistics to the stats collector. */ pgstat_send_wal(true); @@ -577,9 +573,9 @@ HandleCheckpointerInterrupts(void) * updates the statistics, increment the checkpoint request and send * the statistics to the stats collector. */ - BgWriterStats.m_requested_checkpoints++; + PendingCheckpointerStats.m_requested_checkpoints++; ShutdownXLOG(0, 0); - pgstat_send_bgwriter(); + pgstat_send_checkpointer(); pgstat_send_wal(true); /* Normal exit from the checkpointer is here */ @@ -719,9 +715,9 @@ CheckpointWriteDelay(int flags, double progress) CheckArchiveTimeout(); /* - * Report interim activity statistics to the stats collector. + * Report interim activity statistics. */ - pgstat_send_bgwriter(); + pgstat_send_checkpointer(); /* * This sleep used to be connected to bgwriter_delay, typically 200ms. @@ -1265,8 +1261,10 @@ AbsorbSyncRequests(void) LWLockAcquire(CheckpointerCommLock, LW_EXCLUSIVE); /* Transfer stats counts into pending pgstats message */ - BgWriterStats.m_buf_written_backend += CheckpointerShmem->num_backend_writes; - BgWriterStats.m_buf_fsync_backend += CheckpointerShmem->num_backend_fsync; + PendingCheckpointerStats.m_buf_written_backend + += CheckpointerShmem->num_backend_writes; + PendingCheckpointerStats.m_buf_fsync_backend + += CheckpointerShmem->num_backend_fsync; CheckpointerShmem->num_backend_writes = 0; CheckpointerShmem->num_backend_fsync = 0; diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index 11702f2a804..56755cb92b6 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -128,7 +128,8 @@ char *pgstat_stat_tmpname = NULL; * Stored directly in a stats message structure so they can be sent * without needing to copy things around. We assume these init to zeroes. */ -PgStat_MsgBgWriter BgWriterStats; +PgStat_MsgBgWriter PendingBgWriterStats; +PgStat_MsgCheckpointer PendingCheckpointerStats; PgStat_MsgWal WalStats; /* @@ -348,6 +349,7 @@ static void pgstat_recv_analyze(PgStat_MsgAnalyze *msg, int len); static void pgstat_recv_anl_ancestors(PgStat_MsgAnlAncestors *msg, int len); static void pgstat_recv_archiver(PgStat_MsgArchiver *msg, int len); static void pgstat_recv_bgwriter(PgStat_MsgBgWriter *msg, int len); +static void pgstat_recv_checkpointer(PgStat_MsgCheckpointer *msg, int len); static void pgstat_recv_wal(PgStat_MsgWal *msg, int len); static void pgstat_recv_slru(PgStat_MsgSLRU *msg, int len); static void pgstat_recv_funcstat(PgStat_MsgFuncstat *msg, int len); @@ -2830,6 +2832,37 @@ pgstat_fetch_stat_archiver(void) return &archiverStats; } +/* + * --------- + * pgstat_fetch_stat_bgwriter() - + * + * Support function for the SQL-callable pgstat* functions. Returns + * a pointer to the bgwriter statistics struct. + * --------- + */ +PgStat_BgWriterStats * +pgstat_fetch_stat_bgwriter(void) +{ + backend_read_statsfile(); + + return &globalStats.bgwriter; +} + +/* + * --------- + * pgstat_fetch_stat_checkpointer() - + * + * Support function for the SQL-callable pgstat* functions. Returns + * a pointer to the checkpointer statistics struct. + * --------- + */ +PgStat_CheckpointerStats * +pgstat_fetch_stat_checkpointer(void) +{ + backend_read_statsfile(); + + return &globalStats.checkpointer; +} /* * --------- @@ -3025,19 +3058,51 @@ pgstat_send_bgwriter(void) * this case, avoid sending a completely empty message to the stats * collector. */ - if (memcmp(&BgWriterStats, &all_zeroes, sizeof(PgStat_MsgBgWriter)) == 0) + if (memcmp(&PendingBgWriterStats, &all_zeroes, sizeof(PgStat_MsgBgWriter)) == 0) + return; + + /* + * Prepare and send the message + */ + pgstat_setheader(&PendingBgWriterStats.m_hdr, PGSTAT_MTYPE_BGWRITER); + pgstat_send(&PendingBgWriterStats, sizeof(PendingBgWriterStats)); + + /* + * Clear out the statistics buffer, so it can be re-used. + */ + MemSet(&PendingBgWriterStats, 0, sizeof(PendingBgWriterStats)); +} + +/* ---------- + * pgstat_send_checkpointer() - + * + * Send checkpointer statistics to the collector + * ---------- + */ +void +pgstat_send_checkpointer(void) +{ + /* We assume this initializes to zeroes */ + static const PgStat_MsgCheckpointer all_zeroes; + + /* + * This function can be called even if nothing at all has happened. In + * this case, avoid sending a completely empty message to the stats + * collector. + */ + if (memcmp(&PendingCheckpointerStats, &all_zeroes, sizeof(PgStat_MsgCheckpointer)) == 0) return; /* * Prepare and send the message */ - pgstat_setheader(&BgWriterStats.m_hdr, PGSTAT_MTYPE_BGWRITER); - pgstat_send(&BgWriterStats, sizeof(BgWriterStats)); + pgstat_setheader(&PendingCheckpointerStats.m_hdr, PGSTAT_MTYPE_CHECKPOINTER); + pgstat_send(&PendingCheckpointerStats, sizeof(PendingCheckpointerStats)); /* * Clear out the statistics buffer, so it can be re-used. */ - MemSet(&BgWriterStats, 0, sizeof(BgWriterStats)); + MemSet(&PendingCheckpointerStats, 0, sizeof(PendingCheckpointerStats)); } /* ---------- @@ -3382,6 +3447,10 @@ PgstatCollectorMain(int argc, char *argv[]) pgstat_recv_bgwriter(&msg.msg_bgwriter, len); break; + case PGSTAT_MTYPE_CHECKPOINTER: + pgstat_recv_checkpointer(&msg.msg_checkpointer, len); + break; + case PGSTAT_MTYPE_WAL: pgstat_recv_wal(&msg.msg_wal, len); break; @@ -3934,6 +4003,7 @@ pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep) bool found; const char *statfile = permanent ? PGSTAT_STAT_PERMANENT_FILENAME : pgstat_stat_filename; int i; + TimestampTz ts; /* * The tables will live in pgStatLocalContext. @@ -3962,15 +4032,16 @@ pgstat_read_statsfiles(Oid onlydb, bool permanent, bool deep) * Set the current timestamp (will be kept only in case we can't load an * existing statsfile). */ - globalStats.stat_reset_timestamp = GetCurrentTimestamp(); - archiverStats.stat_reset_timestamp = globalStats.stat_reset_timestamp; - walStats.stat_reset_timestamp = globalStats.stat_reset_timestamp; + ts = GetCurrentTimestamp(); + globalStats.bgwriter.stat_reset_timestamp = ts; + archiverStats.stat_reset_timestamp = ts; + walStats.stat_reset_timestamp = ts; /* * Set the same reset timestamp for all SLRU items too. */ for (i = 0; i < SLRU_NUM_ELEMENTS; i++) - slruStats[i].stat_reset_timestamp = globalStats.stat_reset_timestamp; + slruStats[i].stat_reset_timestamp = ts; /* * Try to open the stats file. If it doesn't exist, the backends simply @@ -5055,9 +5126,9 @@ pgstat_recv_resetsharedcounter(PgStat_MsgResetsharedcounter *msg, int len) { if (msg->m_resettarget == RESET_BGWRITER) { - /* Reset the global background writer statistics for the cluster. */ + /* Reset the global, bgwriter and checkpointer statistics for the cluster. */ memset(&globalStats, 0, sizeof(globalStats)); - globalStats.stat_reset_timestamp = GetCurrentTimestamp(); + globalStats.bgwriter.stat_reset_timestamp = GetCurrentTimestamp(); } else if (msg->m_resettarget == RESET_ARCHIVER) { @@ -5345,16 +5416,27 @@ pgstat_recv_archiver(PgStat_MsgArchiver *msg, int len) static void pgstat_recv_bgwriter(PgStat_MsgBgWriter *msg, int len) { - globalStats.timed_checkpoints += msg->m_timed_checkpoints; - globalStats.requested_checkpoints += msg->m_requested_checkpoints; - globalStats.checkpoint_write_time += msg->m_checkpoint_write_time; - globalStats.checkpoint_sync_time += msg->m_checkpoint_sync_time; - globalStats.buf_written_checkpoints += msg->m_buf_written_checkpoints; - globalStats.buf_written_clean += msg->m_buf_written_clean; - globalStats.maxwritten_clean += msg->m_maxwritten_clean; - globalStats.buf_written_backend += msg->m_buf_written_backend; - globalStats.buf_fsync_backend += msg->m_buf_fsync_backend; - globalStats.buf_alloc += msg->m_buf_alloc; + globalStats.bgwriter.buf_written_clean += msg->m_buf_written_clean; + globalStats.bgwriter.maxwritten_clean += msg->m_maxwritten_clean; + globalStats.bgwriter.buf_alloc += msg->m_buf_alloc; +} + +/* ---------- + * pgstat_recv_checkpointer() - + * + * Process a CHECKPOINTER message. + * ---------- + */ +static void +pgstat_recv_checkpointer(PgStat_MsgCheckpointer *msg, int len) +{ + globalStats.checkpointer.timed_checkpoints += msg->m_timed_checkpoints; + globalStats.checkpointer.requested_checkpoints += msg->m_requested_checkpoints; + globalStats.checkpointer.checkpoint_write_time += msg->m_checkpoint_write_time; + globalStats.checkpointer.checkpoint_sync_time += msg->m_checkpoint_sync_time; + globalStats.checkpointer.buf_written_checkpoints += msg->m_buf_written_checkpoints; + globalStats.checkpointer.buf_written_backend += msg->m_buf_written_backend; + globalStats.checkpointer.buf_fsync_backend += msg->m_buf_fsync_backend; } /* ---------- diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 33d99f604ad..77685bdde28 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -2137,7 +2137,7 @@ BufferSync(int flags) if (SyncOneBuffer(buf_id, false, &wb_context) & BUF_WRITTEN) { TRACE_POSTGRESQL_BUFFER_SYNC_WRITTEN(buf_id); - BgWriterStats.m_buf_written_checkpoints++; + PendingCheckpointerStats.m_buf_written_checkpoints++; num_written++; } } @@ -2247,7 +2247,7 @@ BgBufferSync(WritebackContext *wb_context) strategy_buf_id = StrategySyncStart(&strategy_passes, &recent_alloc); /* Report buffer alloc counts to pgstat */ - BgWriterStats.m_buf_alloc += recent_alloc; + PendingBgWriterStats.m_buf_alloc += recent_alloc; /* * If we're not running the LRU scan, just stop after doing the stats @@ -2437,7 +2437,7 @@ BgBufferSync(WritebackContext *wb_context) reusable_buffers++; if (++num_written >= bgwriter_lru_maxpages) { - BgWriterStats.m_maxwritten_clean++; + PendingBgWriterStats.m_maxwritten_clean++; break; } } @@ -2445,7 +2445,7 @@ BgBufferSync(WritebackContext *wb_context) reusable_buffers++; } - BgWriterStats.m_buf_written_clean += num_written; + PendingBgWriterStats.m_buf_written_clean += num_written; #ifdef BGW_DEBUG elog(DEBUG1, "bgwriter: recent_alloc=%u smoothed=%.2f delta=%ld ahead=%d density=%.2f reusable_est=%d upcoming_est=%d scanned=%d wrote=%d reusable=%d", diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index f0e09eae4d6..ff5aedc99cb 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -36,9 +36,6 @@ #define HAS_PGSTAT_PERMISSIONS(role) (is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS) || has_privs_of_role(GetUserId(), role)) -/* Global bgwriter statistics, from bgwriter.c */ -extern PgStat_MsgBgWriter bgwriterStats; - Datum pg_stat_get_numscans(PG_FUNCTION_ARGS) { @@ -1732,69 +1729,71 @@ pg_stat_get_db_sessions_killed(PG_FUNCTION_ARGS) Datum pg_stat_get_bgwriter_timed_checkpoints(PG_FUNCTION_ARGS) { - PG_RETURN_INT64(pgstat_fetch_global()->timed_checkpoints); + PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->timed_checkpoints); } Datum pg_stat_get_bgwriter_requested_checkpoints(PG_FUNCTION_ARGS) { - PG_RETURN_INT64(pgstat_fetch_global()->requested_checkpoints); + PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->requested_checkpoints); } Datum pg_stat_get_bgwriter_buf_written_checkpoints(PG_FUNCTION_ARGS) { - PG_RETURN_INT64(pgstat_fetch_global()->buf_written_checkpoints); + PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->buf_written_checkpoints); } Datum pg_stat_get_bgwriter_buf_written_clean(PG_FUNCTION_ARGS) { - PG_RETURN_INT64(pgstat_fetch_global()->buf_written_clean); + PG_RETURN_INT64(pgstat_fetch_stat_bgwriter()->buf_written_clean); } Datum pg_stat_get_bgwriter_maxwritten_clean(PG_FUNCTION_ARGS) { - PG_RETURN_INT64(pgstat_fetch_global()->maxwritten_clean); + PG_RETURN_INT64(pgstat_fetch_stat_bgwriter()->maxwritten_clean); } Datum pg_stat_get_checkpoint_write_time(PG_FUNCTION_ARGS) { /* time is already in msec, just convert to double for presentation */ - PG_RETURN_FLOAT8((double) pgstat_fetch_global()->checkpoint_write_time); + PG_RETURN_FLOAT8((double) + pgstat_fetch_stat_checkpointer()->checkpoint_write_time); } Datum pg_stat_get_checkpoint_sync_time(PG_FUNCTION_ARGS) { /* time is already in msec, just convert to double for presentation */ - PG_RETURN_FLOAT8((double) pgstat_fetch_global()->checkpoint_sync_time); + PG_RETURN_FLOAT8((double) + pgstat_fetch_stat_checkpointer()->checkpoint_sync_time); } Datum pg_stat_get_bgwriter_stat_reset_time(PG_FUNCTION_ARGS) { - PG_RETURN_TIMESTAMPTZ(pgstat_fetch_global()->stat_reset_timestamp); + PG_RETURN_TIMESTAMPTZ(pgstat_fetch_stat_bgwriter()->stat_reset_timestamp); } Datum pg_stat_get_buf_written_backend(PG_FUNCTION_ARGS) { - PG_RETURN_INT64(pgstat_fetch_global()->buf_written_backend); + PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->buf_written_backend); } Datum pg_stat_get_buf_fsync_backend(PG_FUNCTION_ARGS) { - PG_RETURN_INT64(pgstat_fetch_global()->buf_fsync_backend); + PG_RETURN_INT64(pgstat_fetch_stat_checkpointer()->buf_fsync_backend); } Datum pg_stat_get_buf_alloc(PG_FUNCTION_ARGS) { - PG_RETURN_INT64(pgstat_fetch_global()->buf_alloc); + PG_RETURN_INT64(pgstat_fetch_stat_bgwriter()->buf_alloc); } /* diff --git a/src/include/pgstat.h b/src/include/pgstat.h index 9612c0a6c27..2068a68a5ff 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -72,6 +72,7 @@ typedef enum StatMsgType PGSTAT_MTYPE_ANL_ANCESTORS, PGSTAT_MTYPE_ARCHIVER, PGSTAT_MTYPE_BGWRITER, + PGSTAT_MTYPE_CHECKPOINTER, PGSTAT_MTYPE_WAL, PGSTAT_MTYPE_SLRU, PGSTAT_MTYPE_FUNCSTAT, @@ -470,17 +471,27 @@ typedef struct PgStat_MsgBgWriter { PgStat_MsgHdr m_hdr; + PgStat_Counter m_buf_written_clean; + PgStat_Counter m_maxwritten_clean; + PgStat_Counter m_buf_alloc; +} PgStat_MsgBgWriter; + +/* ---------- + * PgStat_MsgCheckpointer Sent by the checkpointer to update statistics. + * ---------- + */ +typedef struct PgStat_MsgCheckpointer +{ + PgStat_MsgHdr m_hdr; + PgStat_Counter m_timed_checkpoints; PgStat_Counter m_requested_checkpoints; PgStat_Counter m_buf_written_checkpoints; - PgStat_Counter m_buf_written_clean; - PgStat_Counter m_maxwritten_clean; PgStat_Counter m_buf_written_backend; PgStat_Counter m_buf_fsync_backend; - PgStat_Counter m_buf_alloc; PgStat_Counter m_checkpoint_write_time; /* times in milliseconds */ PgStat_Counter m_checkpoint_sync_time; -} PgStat_MsgBgWriter; +} PgStat_MsgCheckpointer; /* ---------- * PgStat_MsgWal Sent by backends and background processes to update WAL statistics. @@ -700,6 +711,7 @@ typedef union PgStat_Msg PgStat_MsgAnlAncestors msg_anl_ancestors; PgStat_MsgArchiver msg_archiver; PgStat_MsgBgWriter msg_bgwriter; + PgStat_MsgCheckpointer msg_checkpointer; PgStat_MsgWal msg_wal; PgStat_MsgSLRU msg_slru; PgStat_MsgFuncstat msg_funcstat; @@ -721,7 +733,7 @@ typedef union PgStat_Msg * ------------------------------------------------------------ */ -#define PGSTAT_FILE_FORMAT_ID 0x01A5BCA2 +#define PGSTAT_FILE_FORMAT_ID 0x01A5BCA3 /* ---------- * PgStat_StatDBEntry The collector's data per database @@ -842,9 +854,20 @@ typedef struct PgStat_ArchiverStats } PgStat_ArchiverStats; /* - * Global statistics kept in the stats collector + * Background writer statistics kept in the stats collector */ -typedef struct PgStat_GlobalStats +typedef struct PgStat_BgWriterStats +{ + PgStat_Counter buf_written_clean; + PgStat_Counter maxwritten_clean; + PgStat_Counter buf_alloc; + TimestampTz stat_reset_timestamp; +} PgStat_BgWriterStats; + +/* + * Checkpointer statistics kept in the stats collector + */ +typedef struct PgStat_CheckpointerStats { TimestampTz stats_timestamp; /* time of stats file update */ PgStat_Counter timed_checkpoints; @@ -852,12 +875,19 @@ typedef struct PgStat_GlobalStats PgStat_Counter checkpoint_write_time; /* times in milliseconds */ PgStat_Counter checkpoint_sync_time; PgStat_Counter buf_written_checkpoints; - PgStat_Counter buf_written_clean; - PgStat_Counter maxwritten_clean; PgStat_Counter buf_written_backend; PgStat_Counter buf_fsync_backend; - PgStat_Counter buf_alloc; - TimestampTz stat_reset_timestamp; +} PgStat_CheckpointerStats; + +/* + * Global statistics kept in the stats collector + */ +typedef struct PgStat_GlobalStats +{ + TimestampTz stats_timestamp; /* time of stats file update */ + + PgStat_CheckpointerStats checkpointer; + PgStat_BgWriterStats bgwriter; } PgStat_GlobalStats; /* @@ -939,7 +969,13 @@ extern char *pgstat_stat_filename; /* * BgWriter statistics counters are updated directly by bgwriter and bufmgr */ -extern PgStat_MsgBgWriter BgWriterStats; +extern PgStat_MsgBgWriter PendingBgWriterStats; + +/* + * Checkpointer statistics counters are updated directly by checkpointer and + * bufmgr. + */ +extern PgStat_MsgCheckpointer PendingCheckpointerStats; /* * WAL statistics counter is updated by backends and background processes @@ -1091,6 +1127,7 @@ extern void pgstat_twophase_postabort(TransactionId xid, uint16 info, extern void pgstat_send_archiver(const char *xlog, bool failed); extern void pgstat_send_bgwriter(void); +extern void pgstat_send_checkpointer(void); extern void pgstat_send_wal(bool force); /* ---------- @@ -1102,6 +1139,8 @@ extern PgStat_StatDBEntry *pgstat_fetch_stat_dbentry(Oid dbid); extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid relid); extern PgStat_StatFuncEntry *pgstat_fetch_stat_funcentry(Oid funcid); extern PgStat_ArchiverStats *pgstat_fetch_stat_archiver(void); +extern PgStat_BgWriterStats *pgstat_fetch_stat_bgwriter(void); +extern PgStat_CheckpointerStats *pgstat_fetch_stat_checkpointer(void); extern PgStat_GlobalStats *pgstat_fetch_global(void); extern PgStat_WalStats *pgstat_fetch_stat_wal(void); extern PgStat_SLRUStats *pgstat_fetch_slru(void); |