On Fri, Mar 22, 2019 at 11:46 PM legrand legrand
<legrand_legr...@hotmail.com> wrote:
>
> Here is a rebased and corrected version .

This patch has multiple trailing whitespace, indent and coding style
issues.  You should consider running pg_indent before submitting a
patch.  I attach the diff after running pgindent if you want more
details about the various issues.

- *     Track statement execution times across a whole database cluster.
+ *     Track statement planning and execution times across a whole cluster.

if we're changing this, we should also fix the fact that's it's not
tracking only the time but various resources?

+       /* calc differences of buffer counters. */
+       bufusage.shared_blks_hit =
+           pgBufferUsage.shared_blks_hit - bufusage_start.shared_blks_hit;
[...]

This is an exact duplication of pgss_ProcessUtility(), it's probably
better to create a macro or a function for that instead.

+               pgss_store("",
+                  parse->queryId,          /* signal that it's a
utility stmt */
+                  -1,

the comment makes no sense, and also you can't pass an empty query
string / unknown len.  There's no guarantee that the entry for the
given queryId won't have been evicted, and in this case you'll create
a new and unrelated entry.

@@ -832,13 +931,13 @@ pgss_post_parse_analyze(ParseState *pstate, Query *query)
     * the normalized string would be the same as the query text anyway, so
     * there's no need for an early entry.
     */
-   if (jstate.clocations_count > 0)
        pgss_store(pstate->p_sourcetext,

Why did you remove this?  pgss_store() isn't free, and asking to
generate a normalized query for a query that doesn't have any constant
or storing the entry early won't do anything useful AFAICT.  Though if
that's useful, you definitely can't remove the test without adapting
the comment and the indentation.

@@ -1249,15 +1351,19 @@ pgss_store(const char *query, uint64 queryId,
        if (e->counters.calls == 0)
            e->counters.usage = USAGE_INIT;

-       e->counters.calls += 1;
-       e->counters.total_time += total_time;
-       if (e->counters.calls == 1)
+       if (planning_time == 0)
+       {
+           e->counters.calls += 1;
+           e->counters.total_time += total_time;
+       }
+
+       if (e->counters.calls == 1 && planning_time == 0)
        {
            e->counters.min_time = total_time;
            e->counters.max_time = total_time;
            e->counters.mean_time = total_time;
        }
-       else
+       else if(planning_time == 0)
        {
            /*
             * Welford's method for accurately computing variance. See
@@ -1276,6 +1382,9 @@ pgss_store(const char *query, uint64 queryId,
            if (e->counters.max_time < total_time)
                e->counters.max_time = total_time;
        }
+       if (planning_time > 0)
+           e->counters.plans += 1;
+       e->counters.planning_time += planning_time;

there are 4 tests to check if planning_time is zero or not, it's quite
messy.  Could you refactor the code to avoid so many tests?  It would
probably be useful to add some asserts to check that we don't provide
both planning_time == 0 and execution related values.  The function's
comment would also need to be adapted to mention the new rationale
with planning_time.

     * hash table entry for the PREPARE (with hash calculated from the query
     * string), and then a different one with the same query string (but hash
     * calculated from the query tree) would be used to accumulate costs of
-    * ensuing EXECUTEs.  This would be confusing, and inconsistent with other
-    * cases where planning time is not included at all.
+    * ensuing EXECUTEs.

the comment about confusing behavior is still valid.

>
> Columns naming has not been modified, I would propose to change it to:
>  - plans: ok
>  - planning_time --> plan_time
>  - calls: ok
>  - total_time --> exec_time
>  - {min,max,mean,stddev}_time: ok
>  - new total_time (being the sum of plan_time and exec_time)

plan_time and exec_time are accumulated counters, so we need to keep
the total_ prefix in any case.  I think it's ok to break the function
output names if we keep some kind of compatibility at the view level
(which can keep total_time as the sum of total_plan_time and
total_exec_time), so current queries against the view wouldn't break,
and get what they probably wanted.
diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index 3da490b66d..8c20c91200 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -304,8 +304,8 @@ PG_FUNCTION_INFO_V1(pg_stat_statements);
 static void pgss_shmem_startup(void);
 static void pgss_shmem_shutdown(int code, Datum arg);
 static PlannedStmt *pgss_planner_hook(Query *parse,
-									  int cursorOptions,
-									  ParamListInfo boundParams);
+				  int cursorOptions,
+				  ParamListInfo boundParams);
 static void pgss_post_parse_analyze(ParseState *pstate, Query *query);
 static void pgss_ExecutorStart(QueryDesc *queryDesc, int eflags);
 static void pgss_ExecutorRun(QueryDesc *queryDesc,
@@ -789,19 +789,20 @@ error:
 /*
  * Planner hook: forward to regular planner, but measure planning time.
  */
-static PlannedStmt *pgss_planner_hook(Query *parse,
-									  int cursorOptions,
-									  ParamListInfo boundParams)
+static PlannedStmt *
+pgss_planner_hook(Query *parse,
+				  int cursorOptions,
+				  ParamListInfo boundParams)
 {
 	PlannedStmt *result;
 	BufferUsage bufusage_start,
 				bufusage;
 
-		bufusage_start = pgBufferUsage;
+	bufusage_start = pgBufferUsage;
 	if (pgss_enabled())
 	{
-		instr_time		start;
-		instr_time		duration;
+		instr_time	start;
+		instr_time	duration;
 
 		INSTR_TIME_SET_CURRENT(start);
 
@@ -850,8 +851,8 @@ static PlannedStmt *pgss_planner_hook(Query *parse,
 		bufusage.blk_write_time = pgBufferUsage.blk_write_time;
 		INSTR_TIME_SUBTRACT(bufusage.blk_write_time, bufusage_start.blk_write_time);
 
-				pgss_store("",
-				   parse->queryId,			/* signal that it's a utility stmt */
+		pgss_store("",
+				   parse->queryId,	/* signal that it's a utility stmt */
 				   -1,
 				   0,
 				   0,
@@ -931,15 +932,15 @@ pgss_post_parse_analyze(ParseState *pstate, Query *query)
 	 * the normalized string would be the same as the query text anyway, so
 	 * there's no need for an early entry.
 	 */
-		pgss_store(pstate->p_sourcetext,
-				   query->queryId,
-				   query->stmt_location,
-				   query->stmt_len,
-				   0,
-				   0,
-				   0,
-				   NULL,
-				   &jstate);
+	pgss_store(pstate->p_sourcetext,
+			   query->queryId,
+			   query->stmt_location,
+			   query->stmt_len,
+			   0,
+			   0,
+			   0,
+			   NULL,
+			   &jstate);
 }
 
 /*
@@ -1044,7 +1045,7 @@ pgss_ExecutorEnd(QueryDesc *queryDesc)
 				   queryDesc->plannedstmt->stmt_location,
 				   queryDesc->plannedstmt->stmt_len,
 				   queryDesc->totaltime->total * 1000.0,	/* convert to msec */
-					0,
+				   0,
 				   queryDesc->estate->es_processed,
 				   &queryDesc->totaltime->bufusage,
 				   NULL);
@@ -1255,8 +1256,9 @@ pgss_store(const char *query, uint64 queryId,
 		queryId = pgss_hash_string(query, query_len);
 
 		/*
-		 * If we are unlucky enough to get a hash of zero(invalid), use queryID
-		 * as 2 instead, queryID 1 is already in use for normal statements.
+		 * If we are unlucky enough to get a hash of zero(invalid), use
+		 * queryID as 2 instead, queryID 1 is already in use for normal
+		 * statements.
 		 */
 		if (queryId == UINT64CONST(0))
 			queryId = UINT64CONST(2);
@@ -1355,7 +1357,7 @@ pgss_store(const char *query, uint64 queryId,
 		{
 			e->counters.calls += 1;
 			e->counters.total_time += total_time;
-		}	
+		}
 
 		if (e->counters.calls == 1 && planning_time == 0)
 		{
@@ -1363,7 +1365,7 @@ pgss_store(const char *query, uint64 queryId,
 			e->counters.max_time = total_time;
 			e->counters.mean_time = total_time;
 		}
-		else if(planning_time == 0)
+		else if (planning_time == 0)
 		{
 			/*
 			 * Welford's method for accurately computing variance. See

Reply via email to