]> granicus.if.org Git - postgresql/commitdiff
Fix issues around EXPLAIN with JIT.
authorAndres Freund <andres@anarazel.de>
Wed, 3 Oct 2018 19:48:37 +0000 (12:48 -0700)
committerAndres Freund <andres@anarazel.de>
Wed, 3 Oct 2018 20:11:44 +0000 (13:11 -0700)
I (Andres) was more than a bit hasty in committing 33001fd7a7072d48327
after last minute changes, leading to a number of problems (jit output
was only shown for JIT in parallel workers, and just EXPLAIN without
ANALYZE didn't work).  Lukas luckily found these issues quickly.

Instead of combining instrumentation in in standard_ExecutorEnd(), do
so on demand in the new ExplainPrintJITSummary().

Also update a documentation example of the JIT output, changed in
52050ad8ebec8d831.

Author: Lukas Fittl, with minor changes by me
Discussion: https://postgr.es/m/CAP53PkxmgJht69pabxBXJBM+0oc6kf3KHMborLP7H2ouJ0CCtQ@mail.gmail.com
Backpatch: 11, where JIT compilation was introduced

contrib/auto_explain/auto_explain.c
doc/src/sgml/jit.sgml
src/backend/commands/explain.c
src/backend/executor/execMain.c
src/backend/executor/execParallel.c
src/include/commands/explain.h
src/include/nodes/execnodes.h

index b9c0896433409bce3567b541004d653c70865767..03be05129ffe79811f0726a1167ed05f6d9b62ba 100644 (file)
@@ -336,8 +336,7 @@ explain_ExecutorEnd(QueryDesc *queryDesc)
                        if (es->analyze && auto_explain_log_triggers)
                                ExplainPrintTriggers(es, queryDesc);
                        if (es->costs)
-                               ExplainPrintJIT(es, queryDesc->estate->es_jit_flags,
-                                                               queryDesc->estate->es_jit_combined_instr, -1);
+                               ExplainPrintJITSummary(es, queryDesc);
                        ExplainEndOutput(es);
 
                        /* Remove last line break */
index 8387a4f6bee07aa93f43e39b016a2a7f4293f323..a21a07ef71d7ab35086c497bb84504d11be3ff51 100644 (file)
@@ -169,12 +169,8 @@ SET
  Planning Time: 0.133 ms
  JIT:
    Functions: 3
-   Generation Time: 1.259 ms
-   Inlining: false
-   Inlining Time: 0.000 ms
-   Optimization: false
-   Optimization Time: 0.797 ms
-   Emission Time: 5.048 ms
+   Options: Inlining false, Optimization false, Expressions true, Deforming true
+   Timing: Generation 1.259 ms, Inlining 0.000 ms, Optimization 0.797 ms, Emission 5.048 ms, Total 7.104 ms
  Execution Time: 7.416 ms
 </screen>
    As visible here, <acronym>JIT</acronym> was used, but inlining and
index ed6afe79a9f120d1693411db442b288b0cccbc33..799a22e9d5537a6ce97a4512fe9321c9b2c4a0a9 100644 (file)
@@ -564,8 +564,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
         * at a later stage.
         */
        if (es->costs)
-               ExplainPrintJIT(es, queryDesc->estate->es_jit_flags,
-                                               queryDesc->estate->es_jit_combined_instr, -1);
+               ExplainPrintJITSummary(es, queryDesc);
 
        /*
         * Close down the query and free resources.  Include time for this in the
@@ -688,6 +687,32 @@ ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc)
        ExplainCloseGroup("Triggers", "Triggers", false, es);
 }
 
+/*
+ * ExplainPrintJITSummary -
+ *    Print summarized JIT instrumentation from leader and workers
+ */
+void
+ExplainPrintJITSummary(ExplainState *es, QueryDesc *queryDesc)
+{
+       JitInstrumentation ji = {0};
+
+       if (!(queryDesc->estate->es_jit_flags & PGJIT_PERFORM))
+               return;
+
+       /*
+        * Work with a copy instead of modifying the leader state, since this
+        * function may be called twice
+        */
+       if (queryDesc->estate->es_jit)
+               InstrJitAgg(&ji, &queryDesc->estate->es_jit->instr);
+
+       /* If this process has done JIT in parallel workers, merge stats */
+       if (queryDesc->estate->es_jit_worker_instr)
+               InstrJitAgg(&ji, queryDesc->estate->es_jit_worker_instr);
+
+       ExplainPrintJIT(es, queryDesc->estate->es_jit_flags, &ji, -1);
+}
+
 /*
  * ExplainPrintJIT -
  *       Append information about JITing to es->str.
index 04f14c91787bfe83f0c7bdde7dcf333e6c6f585f..572506e7c272f2e4b4deb1f95606d28f4ae9112b 100644 (file)
@@ -495,21 +495,6 @@ standard_ExecutorEnd(QueryDesc *queryDesc)
 
        ExecEndPlan(queryDesc->planstate, estate);
 
-       /*
-        * If this process has done JIT, either merge stats into worker stats, or
-        * use this process' stats as the global stats if no parallelism was used
-        * / no workers did JIT.
-        */
-       if (estate->es_instrument && queryDesc->estate->es_jit)
-       {
-               if (queryDesc->estate->es_jit_combined_instr)
-                       InstrJitAgg(queryDesc->estate->es_jit_combined_instr,
-                                               &queryDesc->estate->es_jit->instr);
-               else
-                       queryDesc->estate->es_jit_combined_instr =
-                               &queryDesc->estate->es_jit->instr;
-       }
-
        /* do away with our snapshots */
        UnregisterSnapshot(estate->es_snapshot);
        UnregisterSnapshot(estate->es_crosscheck_snapshot);
index 7d8bd01994fc28e48bbbdc51910cd2120ed0842e..0fdbd119d9bca92a3df4f81dba2376a04c236420 100644 (file)
@@ -1043,13 +1043,12 @@ ExecParallelRetrieveJitInstrumentation(PlanState *planstate,
 
        /*
         * Accumulate worker JIT instrumentation into the combined JIT
-        * instrumentation, allocating it if required. Note this is kept separate
-        * from the leader's own instrumentation.
+        * instrumentation, allocating it if required.
         */
-       if (!planstate->state->es_jit_combined_instr)
-               planstate->state->es_jit_combined_instr =
+       if (!planstate->state->es_jit_worker_instr)
+               planstate->state->es_jit_worker_instr =
                        MemoryContextAllocZero(planstate->state->es_query_cxt, sizeof(JitInstrumentation));
-       combined = planstate->state->es_jit_combined_instr;
+       combined = planstate->state->es_jit_worker_instr;
 
        /* Accummulate all the workers' instrumentations. */
        for (n = 0; n < shared_jit->num_workers; ++n)
index b0b6f1e15a4340a3e4b508e2a6f207a76473177b..d3f70fda084ebdf203c72c9ed751f7b37901af84 100644 (file)
@@ -81,6 +81,7 @@ extern void ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into,
 extern void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc);
 extern void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc);
 
+extern void ExplainPrintJITSummary(ExplainState *es, QueryDesc *queryDesc);
 extern void ExplainPrintJIT(ExplainState *es, int jit_flags,
                                struct JitInstrumentation *jit_instr, int worker_i);
 
index 2c1bdb60a532f1135eb9c0ccdd1d8797c5f6fa0a..049dc0a3efa46468b23c46ada361048b9ec39285 100644 (file)
@@ -570,13 +570,13 @@ typedef struct EState
         * and with which options.  es_jit is created on-demand when JITing is
         * performed.
         *
-        * es_jit_combined_instr, at the end of query execution with
-        * instrumentation enabled, is the the combined instrumentation
-        * information of leader and followers.
+        * es_jit_combined_instr is the the combined, on demand allocated,
+        * instrumentation from all workers. The leader's instrumentation is kept
+        * separate, and is combined on demand by ExplainPrintJITSummary().
         */
        int                     es_jit_flags;
        struct JitContext *es_jit;
-       struct JitInstrumentation *es_jit_combined_instr;
+       struct JitInstrumentation *es_jit_worker_instr;
 } EState;