From 7ebbf8a5279ee61069a3d89a1aee8d116f7a7525 Mon Sep 17 00:00:00 2001 From: Oleg Tselebrovskiy Date: Tue, 25 Jun 2024 17:24:39 +0700 Subject: [PATCH] Add option for tracking subqueries' wait events --- README.md | 7 ++-- pg_wait_sampling.c | 98 ++++++++++++++++++++++++++++++++++++++++------ pg_wait_sampling.h | 2 +- 3 files changed, 91 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 01aa116..c9ef3f9 100644 --- a/README.md +++ b/README.md @@ -139,15 +139,16 @@ GUCs. | pg_wait_sampling.history_period | int4 | Period for history sampling in milliseconds | 10 | | pg_wait_sampling.profile_period | int4 | Period for profile sampling in milliseconds | 10 | | pg_wait_sampling.profile_pid | bool | Whether profile should be per pid | true | -| pg_wait_sampling.profile_queries | bool | Whether profile should be per query | true | +| pg_wait_sampling.profile_queries | enum | Whether profile should be per query | top | | pg_wait_sampling.sample_cpu | bool | Whether on CPU backends should be sampled | true | If `pg_wait_sampling.profile_pid` is set to false, sampling profile wouldn't be collected in per-process manner. In this case the value of pid could would be always zero and corresponding row contain samples among all the processes. -While `pg_wait_sampling.profile_queries` is set to false `queryid` field in -views will be zero. +If `pg_wait_sampling.profile_queries` is set to `none`, `queryid` field in +views will be zero. If it is set to `top`, queryIds only of top level statements +are recorded. If it is set to `all`, queryIds of nested statements are recorded. If `pg_wait_sampling.sample_cpu` is set to true then processes that are not waiting on anything are also sampled. The wait event columns for such processes diff --git a/pg_wait_sampling.c b/pg_wait_sampling.c index 2cd7c7d..068b553 100644 --- a/pg_wait_sampling.c +++ b/pg_wait_sampling.c @@ -95,6 +95,35 @@ static void pgws_ProcessUtility(PlannedStmt *pstmt, #endif ); +/*---- GUC variables ----*/ + +typedef enum +{ + PGWS_PROFILE_QUERIES_NONE, /* profile no statements */ + PGWS_PROFILE_QUERIES_TOP, /* only top level statements */ + PGWS_PROFILE_QUERIES_ALL /* all statements, including nested ones */ +} PGWSTrackLevel; + +static const struct config_enum_entry pgws_profile_queries_options[] = +{ + {"none", PGWS_PROFILE_QUERIES_NONE, false}, + {"off", PGWS_PROFILE_QUERIES_NONE, false}, + {"no", PGWS_PROFILE_QUERIES_NONE, false}, + {"false", PGWS_PROFILE_QUERIES_NONE, false}, + {"0", PGWS_PROFILE_QUERIES_NONE, false}, + {"top", PGWS_PROFILE_QUERIES_TOP, false}, + {"on", PGWS_PROFILE_QUERIES_TOP, false}, + {"yes", PGWS_PROFILE_QUERIES_TOP, false}, + {"true", PGWS_PROFILE_QUERIES_TOP, false}, + {"1", PGWS_PROFILE_QUERIES_TOP, false}, + {"all", PGWS_PROFILE_QUERIES_ALL, false}, + {NULL, 0, false} +}; + +#define pgws_enabled(level) \ + ((pgws_collector_hdr->profileQueries == PGWS_PROFILE_QUERIES_ALL) || \ + (pgws_collector_hdr->profileQueries == PGWS_PROFILE_QUERIES_TOP && (level) == 0)) + /* * Calculate max processes count. * @@ -185,6 +214,14 @@ shmem_int_guc_check_hook(int *newval, void **extra, GucSource source) return true; } +static bool +shmem_enum_guc_check_hook(int *newval, void **extra, GucSource source) +{ + if (UsedShmemSegAddr == NULL) + return false; + return true; +} + static bool shmem_bool_guc_check_hook(bool *newval, void **extra, GucSource source) { @@ -260,8 +297,8 @@ setup_gucs() else if (!strcmp(name, "pg_wait_sampling.profile_queries")) { profile_queries_found = true; - var->_bool.variable = &pgws_collector_hdr->profileQueries; - pgws_collector_hdr->profileQueries = true; + var->_enum.variable = &pgws_collector_hdr->profileQueries; + pgws_collector_hdr->profileQueries = PGWS_PROFILE_QUERIES_TOP; } else if (!strcmp(name, "pg_wait_sampling.sample_cpu")) { @@ -296,10 +333,10 @@ setup_gucs() PGC_SUSET, 0, shmem_bool_guc_check_hook, NULL, NULL); if (!profile_queries_found) - DefineCustomBoolVariable("pg_wait_sampling.profile_queries", + DefineCustomEnumVariable("pg_wait_sampling.profile_queries", "Sets whether profile should be collected per query.", NULL, - &pgws_collector_hdr->profileQueries, true, - PGC_SUSET, 0, shmem_bool_guc_check_hook, NULL, NULL); + &pgws_collector_hdr->profileQueries, PGWS_PROFILE_QUERIES_TOP, pgws_profile_queries_options, + PGC_SUSET, 0, shmem_enum_guc_check_hook, NULL, NULL); if (!sample_cpu_found) DefineCustomBoolVariable("pg_wait_sampling.sample_cpu", @@ -354,6 +391,8 @@ pgws_shmem_startup(void) pgws_collector_hdr = shm_toc_allocate(toc, sizeof(CollectorShmqHeader)); shm_toc_insert(toc, 0, pgws_collector_hdr); + /* needed to please check_GUC_init */ + pgws_collector_hdr->profileQueries = PGWS_PROFILE_QUERIES_TOP; pgws_collector_mq = shm_toc_allocate(toc, COLLECTOR_QUEUE_SIZE); shm_toc_insert(toc, 1, pgws_collector_mq); pgws_proc_queryids = shm_toc_allocate(toc, @@ -933,10 +972,15 @@ pgws_planner_hook(Query *parse, int cursorOptions, ParamListInfo boundParams) { - PlannedStmt *result; - int i = MyProc - ProcGlobal->allProcs; - if (nesting_level == 0) + PlannedStmt *result; + int i = MyProc - ProcGlobal->allProcs; + uint64 save_queryId = 0; + + if (pgws_enabled(nesting_level)) + { + save_queryId = pgws_proc_queryids[i]; pgws_proc_queryids[i] = parse->queryId; + } nesting_level++; PG_TRY(); @@ -957,12 +1001,16 @@ pgws_planner_hook(Query *parse, nesting_level--; if (nesting_level == 0) pgws_proc_queryids[i] = UINT64CONST(0); + else if (pgws_enabled(nesting_level)) + pgws_proc_queryids[i] = save_queryId; } PG_CATCH(); { nesting_level--; if (nesting_level == 0) pgws_proc_queryids[i] = UINT64CONST(0); + else if (pgws_enabled(nesting_level)) + pgws_proc_queryids[i] = save_queryId; PG_RE_THROW(); } PG_END_TRY(); @@ -977,9 +1025,8 @@ static void pgws_ExecutorStart(QueryDesc *queryDesc, int eflags) { int i = MyProc - ProcGlobal->allProcs; - if (nesting_level == 0) + if (pgws_enabled(nesting_level)) pgws_proc_queryids[i] = queryDesc->plannedstmt->queryId; - if (prev_ExecutorStart) prev_ExecutorStart(queryDesc, eflags); else @@ -991,6 +1038,9 @@ pgws_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once) { + int i = MyProc - ProcGlobal->allProcs; + uint64 save_queryId = pgws_proc_queryids[i]; + nesting_level++; PG_TRY(); { @@ -999,10 +1049,18 @@ pgws_ExecutorRun(QueryDesc *queryDesc, else standard_ExecutorRun(queryDesc, direction, count, execute_once); nesting_level--; + if (nesting_level == 0) + pgws_proc_queryids[i] = UINT64CONST(0); + else + pgws_proc_queryids[i] = save_queryId; } PG_CATCH(); { nesting_level--; + if (nesting_level == 0) + pgws_proc_queryids[i] = UINT64CONST(0); + else + pgws_proc_queryids[i] = save_queryId; PG_RE_THROW(); } PG_END_TRY(); @@ -1011,6 +1069,9 @@ pgws_ExecutorRun(QueryDesc *queryDesc, static void pgws_ExecutorFinish(QueryDesc *queryDesc) { + int i = MyProc - ProcGlobal->allProcs; + uint64 save_queryId = pgws_proc_queryids[i]; + nesting_level++; PG_TRY(); { @@ -1019,10 +1080,15 @@ pgws_ExecutorFinish(QueryDesc *queryDesc) else standard_ExecutorFinish(queryDesc); nesting_level--; + if (nesting_level == 0) + pgws_proc_queryids[i] = UINT64CONST(0); + else + pgws_proc_queryids[i] = save_queryId; } PG_CATCH(); { nesting_level--; + pgws_proc_queryids[i] = save_queryId; PG_RE_THROW(); } PG_END_TRY(); @@ -1061,10 +1127,14 @@ pgws_ProcessUtility(PlannedStmt *pstmt, #endif ) { - int i = MyProc - ProcGlobal->allProcs; + int i = MyProc - ProcGlobal->allProcs; + uint64 save_queryId = 0; - if (nesting_level == 0) + if (pgws_enabled(nesting_level)) + { + save_queryId = pgws_proc_queryids[i]; pgws_proc_queryids[i] = pstmt->queryId; + } nesting_level++; PG_TRY(); @@ -1098,12 +1168,16 @@ pgws_ProcessUtility(PlannedStmt *pstmt, nesting_level--; if (nesting_level == 0) pgws_proc_queryids[i] = UINT64CONST(0); + else if (pgws_enabled(nesting_level)) + pgws_proc_queryids[i] = save_queryId; } PG_CATCH(); { nesting_level--; if (nesting_level == 0) pgws_proc_queryids[i] = UINT64CONST(0); + else if (pgws_enabled(nesting_level)) + pgws_proc_queryids[i] = save_queryId; PG_RE_THROW(); } PG_END_TRY(); diff --git a/pg_wait_sampling.h b/pg_wait_sampling.h index 7c409e3..a8a550f 100644 --- a/pg_wait_sampling.h +++ b/pg_wait_sampling.h @@ -62,7 +62,7 @@ typedef struct int historyPeriod; int profilePeriod; bool profilePid; - bool profileQueries; + int profileQueries; bool sampleCpu; } CollectorShmqHeader; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy