From 7b0e603bcf1f0ee6814dda30ec9ffad4c3972da3 Mon Sep 17 00:00:00 2001 From: Muhammad Usama Date: Thu, 23 Feb 2023 01:33:23 +0500 Subject: [PATCH] PG-542: Performance improvement of pg_stat_monitor. Saving the client IP address once per the lifetime of a backend. This avoid the expensive operation multiple times, and hence improving performance significantly. --- pg_stat_monitor--2.0.sql | 2 +- pg_stat_monitor.c | 67 ++++++++++++++++++++++------------------ 2 files changed, 38 insertions(+), 31 deletions(-) diff --git a/pg_stat_monitor--2.0.sql b/pg_stat_monitor--2.0.sql index e9957c1..6182fa4 100644 --- a/pg_stat_monitor--2.0.sql +++ b/pg_stat_monitor--2.0.sql @@ -87,7 +87,7 @@ CREATE FUNCTION pg_stat_monitor_internal( OUT username text, OUT dbid oid, OUT datname text, - OUT client_ip int4, + OUT client_ip int8, OUT queryid int8, -- 4 OUT planid int8, diff --git a/pg_stat_monitor.c b/pg_stat_monitor.c index 7de8864..a049030 100644 --- a/pg_stat_monitor.c +++ b/pg_stat_monitor.c @@ -24,6 +24,8 @@ #include "commands/dbcommands.h" #include "commands/explain.h" #include "pg_stat_monitor.h" +#include "libpq/libpq-be.h" + /* * Extension version number, for supporting older extension versions' objects @@ -135,7 +137,7 @@ PG_FUNCTION_INFO_V1(pg_stat_monitor); PG_FUNCTION_INFO_V1(get_histogram_timings); PG_FUNCTION_INFO_V1(pg_stat_monitor_hook_stats); -static uint pg_get_client_addr(bool *ok); +static uint get_client_ip_address_integer(void); static int pg_get_application_name(char *name, int buff_size); static PgBackendStatus *pg_get_backend_status(void); static Datum intarray_get_datum(int32 arr[], int len); @@ -1281,32 +1283,35 @@ pg_get_application_name(char *name, int buff_size) return strlen(name); } +#include +#include + static uint -pg_get_client_addr(bool *ok) +get_client_ip_address_integer(void) { - PgBackendStatus *beentry = pg_get_backend_status(); - char remote_host[NI_MAXHOST]; - int ret; - - remote_host[0] = '\0'; - - if (!beentry) - return ntohl(inet_addr("127.0.0.1")); - - *ok = true; - - ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr, - beentry->st_clientaddr.salen, - remote_host, sizeof(remote_host), - NULL, 0, - NI_NUMERICHOST | NI_NUMERICSERV); - if (ret != 0) - return ntohl(inet_addr("127.0.0.1")); - - if (strcmp(remote_host, "[local]") == 0) - return ntohl(inet_addr("127.0.0.1")); - - return ntohl(inet_addr(remote_host)); + Port *port = MyProcPort; + if (port) + { + char remote_host[NI_MAXHOST]; + int ret; + remote_host[0] = '\0'; + if (port->raddr.addr.ss_family == AF_INET) + { + ret = getnameinfo((const struct sockaddr *)&port->raddr.addr, port->raddr.salen, + remote_host, sizeof(remote_host), + NULL, 0, + NI_NUMERICHOST | NI_NUMERICSERV); + if (ret != 0) + return ntohl(inet_addr("127.0.0.1")); + return ntohl(inet_addr(remote_host)); + } + else if (port->raddr.addr.ss_family == AF_INET6) + { + /* Since we do not support IPv6 as yet */ + return 0; + } + } + return ntohl(inet_addr("127.0.0.1")); } static void @@ -1642,13 +1647,16 @@ pgsm_create_hash_entry(uint64 bucket_id, uint64 queryid, PlanInfo *plan_info) { pgsmEntry *entry; int sec_ctx; - bool found_client_addr = false; char app_name[APPLICATIONNAME_LEN] = ""; char *app_name_ptr = app_name; int app_name_len = 0; MemoryContext oldctx; char *datname = NULL; char *username = NULL; + static uint client_ip = 0xFFFFFFFF; + + if (client_ip == 0xFFFFFFFF) + client_ip = get_client_ip_address_integer(); /* Create an entry in the pgsm memory context */ oldctx = MemoryContextSwitchTo(pgsm_get_ss()->pgsm_mem_cxt); @@ -1665,8 +1673,7 @@ pgsm_create_hash_entry(uint64 bucket_id, uint64 queryid, PlanInfo *plan_info) entry->key.appid = pgsm_hash_string((const char *)app_name_ptr, app_name_len); /* client address */ - entry->key.ip = pg_get_client_addr(&found_client_addr); - + entry->key.ip = client_ip; /* PlanID, if there is one */ entry->key.planid = plan_info ? plan_info->planid : 0; @@ -2026,7 +2033,7 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo, int64 bucketid = entry->key.bucket_id; Oid dbid = entry->key.dbid; Oid userid = entry->key.userid; - uint32 ip = entry->key.ip; + uint64 ip = (uint64)entry->key.ip; uint64 planid = entry->key.planid; uint64 pgsm_query_id = entry->pgsm_query_id; dsa_area *query_dsa_area; @@ -2103,7 +2110,7 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo, * pg_read_all_stats members are allowed */ if (is_allowed_role || userid == GetUserId()) - values[i++] = UInt32GetDatum(ip); + values[i++] = UInt64GetDatum(ip); else nulls[i++] = true;