PG-286: Reduce calls to pgstat_fetch_stat_numbackends().

After couple CPU profiling sessions with perf, it was detected that the
function pgstat_fetch_stat_numbackends() is very expensive, reading the
implementation on PostgreSQL's backend_status.c just confirmed that.

We use that function on pg_stat_monitor to retrieve the application name
and IP address of the client, we now cache the results in order to avoid
calling it for every query being processed.
This commit is contained in:
Diego Fronza
2021-12-03 14:14:31 -03:00
committed by Hamid Akhtar
parent 8c61e24f95
commit b798ffd461

View File

@@ -104,12 +104,11 @@ PG_FUNCTION_INFO_V1(pg_stat_monitor_settings);
PG_FUNCTION_INFO_V1(get_histogram_timings); PG_FUNCTION_INFO_V1(get_histogram_timings);
PG_FUNCTION_INFO_V1(pg_stat_monitor_hook_stats); PG_FUNCTION_INFO_V1(pg_stat_monitor_hook_stats);
static uint pg_get_client_addr(void); static uint pg_get_client_addr(bool *ok);
static int pg_get_application_name(char* application_name); static int pg_get_application_name(char *application_name, bool *ok);
static PgBackendStatus *pg_get_backend_status(void); static PgBackendStatus *pg_get_backend_status(void);
static Datum intarray_get_datum(int32 arr[], int len); static Datum intarray_get_datum(int32 arr[], int len);
#if PG_VERSION_NUM < 140000 #if PG_VERSION_NUM < 140000
DECLARE_HOOK(void pgss_post_parse_analyze, ParseState *pstate, Query *query); DECLARE_HOOK(void pgss_post_parse_analyze, ParseState *pstate, Query *query);
#else #else
@@ -1132,46 +1131,44 @@ pg_get_backend_status(void)
} }
static int static int
pg_get_application_name(char *application_name) pg_get_application_name(char *application_name, bool *ok)
{ {
PgBackendStatus *beentry = pg_get_backend_status(); PgBackendStatus *beentry = pg_get_backend_status();
if (!beentry) if (!beentry)
return snprintf(application_name, APPLICATIONNAME_LEN, "%s", "postmaster"); return snprintf(application_name, APPLICATIONNAME_LEN, "%s", "postmaster");
if (!beentry)
return snprintf(application_name, APPLICATIONNAME_LEN, "%s", "unknown");
*ok = true;
return snprintf(application_name, APPLICATIONNAME_LEN, "%s", beentry->st_appname); return snprintf(application_name, APPLICATIONNAME_LEN, "%s", beentry->st_appname);
} }
static uint static uint
pg_get_client_addr(void) pg_get_client_addr(bool *ok)
{ {
PgBackendStatus *beentry = pg_get_backend_status(); PgBackendStatus *beentry = pg_get_backend_status();
char remote_host[NI_MAXHOST]; char remote_host[NI_MAXHOST];
int ret; int ret;
static uint localhost = 0;
remote_host[0] = '\0'; remote_host[0] = '\0';
if (!beentry) if (!beentry)
return ntohl(inet_addr("127.0.0.1")); return ntohl(inet_addr("127.0.0.1"));
*ok = true;
ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr, ret = pg_getnameinfo_all(&beentry->st_clientaddr.addr,
beentry->st_clientaddr.salen, beentry->st_clientaddr.salen,
remote_host, sizeof(remote_host), remote_host, sizeof(remote_host),
NULL, 0, NULL, 0,
NI_NUMERICHOST | NI_NUMERICSERV); NI_NUMERICHOST | NI_NUMERICSERV);
if (ret != 0) if (ret != 0)
{ return ntohl(inet_addr("127.0.0.1"));
if (localhost == 0)
localhost = ntohl(inet_addr("127.0.0.1"));
return localhost;
}
if (strcmp(remote_host, "[local]") == 0) if (strcmp(remote_host, "[local]") == 0)
{ return ntohl(inet_addr("127.0.0.1"));
if (localhost == 0)
localhost = ntohl(inet_addr("127.0.0.1"));
return localhost;
}
return ntohl(inet_addr(remote_host)); return ntohl(inet_addr(remote_host));
} }
@@ -1191,11 +1188,11 @@ pgss_update_entry(pgssEntry *entry,
BufferUsage *bufusage, BufferUsage *bufusage,
WalUsage *walusage, WalUsage *walusage,
bool reset, bool reset,
pgssStoreKind kind) pgssStoreKind kind,
const char *app_name,
size_t app_name_len)
{ {
int index; int index;
char application_name[APPLICATIONNAME_LEN];
int application_name_len = pg_get_application_name(application_name);
double old_mean; double old_mean;
int message_len = error_info ? strlen (error_info->message) : 0; int message_len = error_info ? strlen (error_info->message) : 0;
int comments_len = comments ? strlen (comments) : 0; int comments_len = comments ? strlen (comments) : 0;
@@ -1264,11 +1261,11 @@ pgss_update_entry(pgssEntry *entry,
e->counters.resp_calls[index]++; e->counters.resp_calls[index]++;
} }
if (plan_text_len > 0) if (plan_text_len > 0 && !e->counters.planinfo.plan_text[0])
_snprintf(e->counters.planinfo.plan_text, plan_info->plan_text, plan_text_len + 1, PLAN_TEXT_LEN); _snprintf(e->counters.planinfo.plan_text, plan_info->plan_text, plan_text_len + 1, PLAN_TEXT_LEN);
if (application_name_len > 0) if (app_name_len > 0 && !e->counters.info.application_name[0])
_snprintf(e->counters.info.application_name, application_name, application_name_len + 1, APPLICATIONNAME_LEN); _snprintf(e->counters.info.application_name, app_name, app_name_len + 1, APPLICATIONNAME_LEN);
e->counters.info.num_relations = num_relations; e->counters.info.num_relations = num_relations;
_snprintf2(e->counters.info.relations, relations, num_relations, REL_LEN); _snprintf2(e->counters.info.relations, relations, num_relations, REL_LEN);
@@ -1465,8 +1462,8 @@ pgss_store(uint64 queryid,
pgssHashKey key; pgssHashKey key;
pgssEntry *entry; pgssEntry *entry;
pgssSharedState *pgss = pgsm_get_ss(); pgssSharedState *pgss = pgsm_get_ss();
char application_name[APPLICATIONNAME_LEN]; static char application_name[APPLICATIONNAME_LEN] = "";
int application_name_len; static int application_name_len = 0;
bool reset = false; bool reset = false;
uint64 bucketid; uint64 bucketid;
uint64 prev_bucket_id; uint64 prev_bucket_id;
@@ -1474,6 +1471,9 @@ pgss_store(uint64 queryid,
uint64 planid; uint64 planid;
uint64 appid; uint64 appid;
char comments[512] = ""; char comments[512] = "";
static bool found_app_name = false;
static bool found_client_addr = false;
static uint client_addr = 0;
/* Monitoring is disabled */ /* Monitoring is disabled */
if (!PGSM_ENABLED) if (!PGSM_ENABLED)
@@ -1492,8 +1492,13 @@ pgss_store(uint64 queryid,
else else
userid = GetUserId(); userid = GetUserId();
application_name_len = pg_get_application_name(application_name); if (!found_app_name)
planid = plan_info ? plan_info->planid: 0; application_name_len = pg_get_application_name(application_name, &found_app_name);
if (!found_client_addr)
client_addr = pg_get_client_addr(&found_client_addr);
planid = plan_info ? plan_info->planid : 0;
appid = djb2_hash((unsigned char *)application_name, application_name_len); appid = djb2_hash((unsigned char *)application_name, application_name_len);
extract_query_comments(query, comments, sizeof(comments)); extract_query_comments(query, comments, sizeof(comments));
@@ -1508,7 +1513,7 @@ pgss_store(uint64 queryid,
key.userid = userid; key.userid = userid;
key.dbid = MyDatabaseId; key.dbid = MyDatabaseId;
key.queryid = queryid; key.queryid = queryid;
key.ip = pg_get_client_addr(); key.ip = client_addr;
key.planid = planid; key.planid = planid;
key.appid = appid; key.appid = appid;
#if PG_VERSION_NUM < 140000 #if PG_VERSION_NUM < 140000
@@ -1597,7 +1602,9 @@ pgss_store(uint64 queryid,
bufusage, /* bufusage */ bufusage, /* bufusage */
walusage, /* walusage */ walusage, /* walusage */
reset, /* reset */ reset, /* reset */
kind); /* kind */ kind, /* kind */
application_name,
application_name_len);
LWLockRelease(pgss->lock); LWLockRelease(pgss->lock);
} }