Re: pgstat_send_connstats() introduces unnecessary timestamp and UDP overhead - Mailing list pgsql-hackers
From | Kyotaro Horiguchi |
---|---|
Subject | Re: pgstat_send_connstats() introduces unnecessary timestamp and UDP overhead |
Date | |
Msg-id | 20210825.145937.1005974779513969180.horikyota.ntt@gmail.com Whole thread Raw |
In response to | Re: pgstat_send_connstats() introduces unnecessary timestamp and UDP overhead (Kyotaro Horiguchi <horikyota.ntt@gmail.com>) |
List | pgsql-hackers |
At Wed, 25 Aug 2021 13:21:52 +0900 (JST), Kyotaro Horiguchi <horikyota.ntt@gmail.com> wrote in > At Wed, 25 Aug 2021 12:51:58 +0900, Michael Paquier <michael@paquier.xyz> wrote in > > - Throttle the frequency where the connection stat packages are sent, > > as of [2]. > > > > Magnus, this open item is assigned to you as the committer of > > 960869d. Could you comment on those issues? > > > > [1]: https://www.postgresql.org/message-id/4095ceb328780d1bdba77ac6d9785fd7577ed047.camel@cybertec.at > > [2]: https://www.postgresql.org/message-id/20210801205501.nyxzxoelqoo4x2qc@alap3.anarazel.de > > About [2], we need to maintain session active/idel times on additional > menbers in backend status. Letting gpgstat_report_activity to > directly scribble on backend status array would work? So the attached is roughly that (just a PoC, of course). - accumulate active and idle time on backend status array. (pgstat_report_activity) - pgstat_get_db_session_time() and friends read pgstat file then sum up relevant members in backend status array. (So it scans on the array for every number of every database X(). - The function pgstat_send_connstats is called only at the end of a connection. It reads backend status element then send the numbers to stats collector. pgstat_shutdown_hook needs to be moved from on_shmem_exit to before_shmem_exit to read MyBEEntry. regards. -- Kyotaro Horiguchi NTT Open Source Software Center diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index 7fcc3f6ded..47973f1e30 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -244,8 +244,6 @@ static int pgStatXactCommit = 0; static int pgStatXactRollback = 0; PgStat_Counter pgStatBlockReadTime = 0; PgStat_Counter pgStatBlockWriteTime = 0; -PgStat_Counter pgStatActiveTime = 0; -PgStat_Counter pgStatTransactionIdleTime = 0; SessionEndType pgStatSessionEndCause = DISCONNECT_NORMAL; /* Record that's written to 2PC state file when pgstat state is persisted */ @@ -323,7 +321,7 @@ static void pgstat_send_tabstat(PgStat_MsgTabstat *tsmsg); static void pgstat_send_funcstats(void); static void pgstat_send_slru(void); static HTAB *pgstat_collect_oids(Oid catalogid, AttrNumber anum_oid); -static void pgstat_send_connstats(bool disconnect, TimestampTz last_report); +static void pgstat_send_connstats(TimestampTz now); static PgStat_TableStatus *get_tabstat_entry(Oid rel_id, bool isshared); @@ -876,10 +874,8 @@ pgstat_report_stat(bool disconnect) return; /* for backends, send connection statistics */ - if (MyBackendType == B_BACKEND) - pgstat_send_connstats(disconnect, last_report); - - last_report = now; + if (MyBackendType == B_BACKEND && disconnect) + pgstat_send_connstats(now); /* * Destroy pgStatTabHash before we start invalidating PgStat_TableEntry @@ -1368,39 +1364,41 @@ pgstat_drop_relation(Oid relid) * pgstat_send_connstats() - * * Tell the collector about session statistics. - * The parameter "disconnect" will be true when the backend exits. - * "last_report" is the last time we were called (0 if never). * ---------- */ static void -pgstat_send_connstats(bool disconnect, TimestampTz last_report) +pgstat_send_connstats(TimestampTz now) { PgStat_MsgConn msg; - long secs; - int usecs; + volatile PgBackendStatus *beentry = MyBEEntry; if (pgStatSock == PGINVALID_SOCKET || !pgstat_track_counts) return; pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_CONNECTION); msg.m_databaseid = MyDatabaseId; + msg.m_disconnect = pgStatSessionEndCause; - /* session time since the last report */ - TimestampDifference(((last_report == 0) ? MyStartTimestamp : last_report), - GetCurrentTimestamp(), - &secs, &usecs); - msg.m_session_time = secs * 1000000 + usecs; + msg.m_count = 1; - msg.m_disconnect = disconnect ? pgStatSessionEndCause : DISCONNECT_NOT_YET; + if (pgstat_track_activities && beentry) + { + msg.m_session_time = + (PgStat_Counter)(now - beentry->st_proc_start_timestamp) * 1000; + msg.m_active_time = beentry->st_session_active_time; + msg.m_idle_in_xact_time = beentry->st_session_idle_time; - msg.m_active_time = pgStatActiveTime; - pgStatActiveTime = 0; - - msg.m_idle_in_xact_time = pgStatTransactionIdleTime; - pgStatTransactionIdleTime = 0; - - /* report a new session only the first time */ - msg.m_count = (last_report == 0) ? 1 : 0; + PGSTAT_BEGIN_WRITE_ACTIVITY(beentry); + beentry->st_session_active_time = 0; + beentry->st_session_idle_time = 0; + PGSTAT_END_WRITE_ACTIVITY(beentry); + } + else + { + msg.m_session_time = 0; + msg.m_active_time = 0; + msg.m_idle_in_xact_time = 0; + } pgstat_send(&msg, sizeof(PgStat_MsgConn)); } @@ -2877,7 +2875,7 @@ pgstat_initialize(void) prevWalUsage = pgWalUsage; /* Set up a process-exit hook to clean up */ - on_shmem_exit(pgstat_shutdown_hook, 0); + before_shmem_exit(pgstat_shutdown_hook, 0); } /* ------------------------------------------------------------ diff --git a/src/backend/utils/activity/backend_status.c b/src/backend/utils/activity/backend_status.c index e19c4506ef..0f0eecc3b4 100644 --- a/src/backend/utils/activity/backend_status.c +++ b/src/backend/utils/activity/backend_status.c @@ -336,6 +336,8 @@ pgstat_bestart(void) lbeentry.st_activity_start_timestamp = 0; lbeentry.st_state_start_timestamp = 0; lbeentry.st_xact_start_timestamp = 0; + lbeentry.st_session_active_time = 0; + lbeentry.st_session_idle_time = 0; lbeentry.st_databaseid = MyDatabaseId; /* We have userid for client-backends, wal-sender and bgworker processes */ @@ -590,9 +592,9 @@ pgstat_report_activity(BackendState state, const char *cmd_str) if (beentry->st_state == STATE_RUNNING || beentry->st_state == STATE_FASTPATH) - pgstat_count_conn_active_time(secs * 1000000 + usecs); + beentry->st_session_active_time += secs * 1000000 + usecs; else - pgstat_count_conn_txn_idle_time(secs * 1000000 + usecs); + beentry->st_session_idle_time += secs * 1000000 + usecs; } /* diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index f0e09eae4d..62b60077c1 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -1635,6 +1635,56 @@ pg_stat_get_db_blk_write_time(PG_FUNCTION_ARGS) PG_RETURN_FLOAT8(result); } +/* XXXXX */ +static double +_pg_stat_active_session_stats(Oid dbid, int type) +{ + int num_backends = pgstat_fetch_stat_numbackends(); + int curr_backend; + TimestampTz now = GetCurrentTimestamp(); + double result = 0.0; + int nsessions = 0; + + + /* Add session time of active backends */ + /* 1-based index */ + for (curr_backend = 1; curr_backend <= num_backends; curr_backend++) + { + LocalPgBackendStatus *local_beentry; + PgBackendStatus *beentry; + + local_beentry = pgstat_fetch_stat_local_beentry(curr_backend); + if (!local_beentry) + continue; + + beentry = &local_beentry->backendStatus; + + if (beentry->st_databaseid != dbid) + continue; + + switch (type) /* define enum !*/ + { + case 0: /* SESSION TIME */ + result += + (double)(now - beentry->st_proc_start_timestamp) / 1000; + break; + case 1: /* SESSION ACTIVE TIME */ + result += (double)beentry->st_session_active_time / 1000; + break; + case 2: /* SESSION IDLE TIME */ + result += (double)beentry->st_session_idle_time / 1000; + break; + case 3: /* SESSION NUMBER */ + nsessions++; + } + } + + if (type < 3) + return result; + + return (double)nsessions; +} + Datum pg_stat_get_db_session_time(PG_FUNCTION_ARGS) { @@ -1646,6 +1696,8 @@ pg_stat_get_db_session_time(PG_FUNCTION_ARGS) if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) != NULL) result = ((double) dbentry->total_session_time) / 1000.0; + result += _pg_stat_active_session_stats(dbid, 0); + PG_RETURN_FLOAT8(result); } @@ -1660,6 +1712,8 @@ pg_stat_get_db_active_time(PG_FUNCTION_ARGS) if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) != NULL) result = ((double) dbentry->total_active_time) / 1000.0; + result += _pg_stat_active_session_stats(dbid, 1); + PG_RETURN_FLOAT8(result); } @@ -1674,6 +1728,8 @@ pg_stat_get_db_idle_in_transaction_time(PG_FUNCTION_ARGS) if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) != NULL) result = ((double) dbentry->total_idle_in_xact_time) / 1000.0; + result += _pg_stat_active_session_stats(dbid, 2); + PG_RETURN_FLOAT8(result); } @@ -1687,6 +1743,7 @@ pg_stat_get_db_sessions(PG_FUNCTION_ARGS) if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) != NULL) result = (int64) (dbentry->n_sessions); + result += (int64)_pg_stat_active_session_stats(dbid, 3); PG_RETURN_INT64(result); } diff --git a/src/include/pgstat.h b/src/include/pgstat.h index f779b48b8c..9311111690 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -931,13 +931,6 @@ extern PgStat_MsgWal WalStats; extern PgStat_Counter pgStatBlockReadTime; extern PgStat_Counter pgStatBlockWriteTime; -/* - * Updated by pgstat_count_conn_*_time macros, called by - * pgstat_report_activity(). - */ -extern PgStat_Counter pgStatActiveTime; -extern PgStat_Counter pgStatTransactionIdleTime; - /* * Updated by the traffic cop and in errfinish() @@ -1039,10 +1032,6 @@ extern void pgstat_initstats(Relation rel); (pgStatBlockReadTime += (n)) #define pgstat_count_buffer_write_time(n) \ (pgStatBlockWriteTime += (n)) -#define pgstat_count_conn_active_time(n) \ - (pgStatActiveTime += (n)) -#define pgstat_count_conn_txn_idle_time(n) \ - (pgStatTransactionIdleTime += (n)) extern void pgstat_count_heap_insert(Relation rel, PgStat_Counter n); extern void pgstat_count_heap_update(Relation rel, bool hot); diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h index 8042b817df..ebd5755247 100644 --- a/src/include/utils/backend_status.h +++ b/src/include/utils/backend_status.h @@ -124,6 +124,10 @@ typedef struct PgBackendStatus TimestampTz st_activity_start_timestamp; TimestampTz st_state_start_timestamp; + /* Session active/idle time in microsecnods */ + int64 st_session_active_time; + int64 st_session_idle_time; + /* Database OID, owning user's OID, connection client address */ Oid st_databaseid; Oid st_userid;
pgsql-hackers by date: