jit_instr_account_workers_v3.patch
application/octet-stream
Filename: jit_instr_account_workers_v3.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
Series: patch v3
| File | + | − |
|---|---|---|
| src/backend/commands/explain.c | 48 | 16 |
| src/backend/executor/execParallel.c | 87 | 0 |
| src/backend/jit/jit.c | 36 | 3 |
| src/backend/jit/llvm/llvmjit.c | 39 | 27 |
| src/backend/jit/llvm/llvmjit_expr.c | 11 | 11 |
| src/include/commands/explain.h | 2 | 1 |
| src/include/executor/execParallel.h | 1 | 0 |
| src/include/jit/jit.h | 27 | 8 |
| src/include/jit/llvmjit.h | 2 | 2 |
| src/include/nodes/execnodes.h | 4 | 0 |
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 16a80a0..f998062 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -564,8 +564,9 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
* at a later stage.
*/
if (queryDesc->estate->es_jit && es->costs &&
- queryDesc->estate->es_jit->created_functions > 0)
- ExplainPrintJIT(es, queryDesc);
+ queryDesc->estate->es_jit->jit_instr.created_functions > 0)
+ ExplainPrintJIT(es, queryDesc->estate->es_jit_flags,
+ &queryDesc->estate->es_jit->jit_instr, -1);
/*
* Close down the query and free resources. Include time for this in the
@@ -690,43 +691,54 @@ ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc)
/*
* ExplainPrintJIT -
- * Append information about JITing to es->str.
+ * Append information about JITing to es->str. Can be used to print
+ * the JIT instrumentation of the backend or that of a specific worker.
*/
void
-ExplainPrintJIT(ExplainState *es, QueryDesc *queryDesc)
+ExplainPrintJIT(ExplainState *es, int jit_flags,
+ JitInstrumentation *jit_instr, int worker_i)
{
- JitContext *jc = queryDesc->estate->es_jit;
+ bool for_workers = (worker_i >= 0);
+ char *jit_group_label = (for_workers ? "Workers JIT" : "JIT");
- ExplainOpenGroup("JIT", "JIT", true, es);
+ ExplainOpenGroup(jit_group_label, jit_group_label, true, es);
- if (es->format == EXPLAIN_FORMAT_TEXT)
+ if (for_workers)
{
- es->indent += 1;
- appendStringInfo(es->str, "JIT:\n");
+ ExplainPropertyInteger("Jit for Worker ", NULL, worker_i, es);
+
+ /* Jump to the specific worker */
+ jit_instr = jit_instr + worker_i;
}
+ else
+ ExplainPropertyText("Jit", "", es);
+
+ if (es->format == EXPLAIN_FORMAT_TEXT)
+ es->indent += 1;
+
+ ExplainPropertyInteger("Functions", NULL, jit_instr->created_functions, es);
- ExplainPropertyInteger("Functions", NULL, jc->created_functions, es);
if (es->analyze && es->timing)
ExplainPropertyFloat("Generation Time", "ms",
- 1000.0 * INSTR_TIME_GET_DOUBLE(jc->generation_counter),
+ 1000.0 * INSTR_TIME_GET_DOUBLE(jit_instr->generation_counter),
3, es);
- ExplainPropertyBool("Inlining", jc->flags & PGJIT_INLINE, es);
+ ExplainPropertyBool("Inlining", jit_flags & PGJIT_INLINE, es);
if (es->analyze && es->timing)
ExplainPropertyFloat("Inlining Time", "ms",
- 1000.0 * INSTR_TIME_GET_DOUBLE(jc->inlining_counter),
+ 1000.0 * INSTR_TIME_GET_DOUBLE(jit_instr->inlining_counter),
3, es);
- ExplainPropertyBool("Optimization", jc->flags & PGJIT_OPT3, es);
+ ExplainPropertyBool("Optimization", jit_flags & PGJIT_OPT3, es);
if (es->analyze && es->timing)
ExplainPropertyFloat("Optimization Time", "ms",
- 1000.0 * INSTR_TIME_GET_DOUBLE(jc->optimization_counter),
+ 1000.0 * INSTR_TIME_GET_DOUBLE(jit_instr->optimization_counter),
3, es);
if (es->analyze && es->timing)
ExplainPropertyFloat("Emission Time", "ms",
- 1000.0 * INSTR_TIME_GET_DOUBLE(jc->emission_counter),
+ 1000.0 * INSTR_TIME_GET_DOUBLE(jit_instr->emission_counter),
3, es);
ExplainCloseGroup("JIT", "JIT", true, es);
@@ -1515,6 +1527,26 @@ ExplainNode(PlanState *planstate, List *ancestors,
ExplainPropertyInteger("Workers Launched", NULL,
nworkers, es);
}
+
+ /* Print per-worker Jit instrumentation. */
+
+ if (es->analyze && es->verbose &&
+ outerPlanState(planstate)->worker_jit_instrument)
+ {
+ PlanState *child = outerPlanState(planstate);
+ int n;
+ SharedJitInstrumentation *w = child->worker_jit_instrument;
+
+ /* TODO: Consider es->costs before printing ? */
+ for (n = 0; n < w->num_workers; ++n)
+ {
+ /* TODO: Just skip for created_functions <= 0 ?? */
+ if (w->jit_instr[n].created_functions > 0)
+ ExplainPrintJIT(es, child->state->es_jit_flags,
+ w->jit_instr, n);
+ }
+ }
+
if (gather->single_copy || es->format != EXPLAIN_FORMAT_TEXT)
ExplainPropertyBool("Single Copy", gather->single_copy, es);
}
diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c
index c93084e..8152099 100644
--- a/src/backend/executor/execParallel.c
+++ b/src/backend/executor/execParallel.c
@@ -37,6 +37,7 @@
#include "executor/nodeSort.h"
#include "executor/nodeSubplan.h"
#include "executor/tqueue.h"
+#include "jit/jit.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/planmain.h"
#include "optimizer/planner.h"
@@ -62,6 +63,7 @@
#define PARALLEL_KEY_INSTRUMENTATION UINT64CONST(0xE000000000000006)
#define PARALLEL_KEY_DSA UINT64CONST(0xE000000000000007)
#define PARALLEL_KEY_QUERY_TEXT UINT64CONST(0xE000000000000008)
+#define PARALLEL_KEY_JIT_INSTRUMENTATION UINT64CONST(0xE000000000000009)
#define PARALLEL_TUPLE_QUEUE_SIZE 65536
@@ -573,9 +575,11 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate,
char *paramlistinfo_space;
BufferUsage *bufusage_space;
SharedExecutorInstrumentation *instrumentation = NULL;
+ SharedJitInstrumentation *jit_instrumentation = NULL;
int pstmt_len;
int paramlistinfo_len;
int instrumentation_len = 0;
+ int jit_instrumentation_len;
int instrument_offset = 0;
Size dsa_minsize = dsa_minimum_size();
char *query_string;
@@ -671,6 +675,17 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate,
shm_toc_estimate_keys(&pcxt->estimator, 1);
}
+ /* Estimate space for JIT instrumentation, if required. */
+ if (estate->es_jit_flags != PGJIT_NONE)
+ {
+ jit_instrumentation_len =
+ offsetof(SharedJitInstrumentation, jit_instr) +
+ sizeof(JitInstrumentation) * nworkers;
+ jit_instrumentation_len = MAXALIGN(jit_instrumentation_len);
+ shm_toc_estimate_chunk(&pcxt->estimator, jit_instrumentation_len);
+ shm_toc_estimate_keys(&pcxt->estimator, 1);
+ }
+
/* Estimate space for DSA area. */
shm_toc_estimate_chunk(&pcxt->estimator, dsa_minsize);
shm_toc_estimate_keys(&pcxt->estimator, 1);
@@ -744,6 +759,17 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate,
pei->instrumentation = instrumentation;
}
+ if (estate->es_jit_flags != PGJIT_NONE)
+ {
+ jit_instrumentation = shm_toc_allocate(pcxt->toc, jit_instrumentation_len);
+ jit_instrumentation->num_workers = nworkers;
+ memset(jit_instrumentation->jit_instr, 0,
+ sizeof(JitInstrumentation) * nworkers);
+ shm_toc_insert(pcxt->toc, PARALLEL_KEY_JIT_INSTRUMENTATION,
+ jit_instrumentation);
+ pei->jit_instrumentation = jit_instrumentation;
+ }
+
/*
* Create a DSA area that can be used by the leader and all workers.
* (However, if we failed to create a DSM and are using private memory
@@ -1004,6 +1030,51 @@ ExecParallelRetrieveInstrumentation(PlanState *planstate,
}
/*
+ * Add up the workers' JIT instrumentation from dynamic shared memory.
+ */
+static void
+ExecParallelRetrieveJitInstrumentation(PlanState *planstate,
+ SharedJitInstrumentation *shared_jit)
+{
+ int n;
+ JitContext *jit = planstate->state->es_jit;
+ MemoryContext oldcontext;
+ int ibytes;
+
+ /*
+ * If the leader hasn't yet created a jit context, allocate a base context.
+ * The provider context will be created on demand.
+ */
+ if (!jit)
+ {
+ planstate->state->es_jit = jit =
+ jit_create_base_context(planstate->state->es_jit_flags);
+ }
+
+ /* Accummulate all the workers' instrumentations. */
+ for (n = 0; n < shared_jit->num_workers; ++n)
+ InstrJitAgg(&jit->jit_instr, &shared_jit->jit_instr[n]);
+
+ /*
+ * Also store the per-worker detail.
+ *
+ * Similar to ExecParallelRetrieveInstrumentation(), allocate the
+ * instrumentation in per-query context.
+ */
+
+ oldcontext = MemoryContextSwitchTo(planstate->state->es_query_cxt);
+ ibytes = offsetof(SharedJitInstrumentation, jit_instr)
+ + mul_size(shared_jit->num_workers, sizeof(JitInstrumentation));
+ ibytes = MAXALIGN(ibytes);
+ elog(LOG, "ibytes : %d; num_workers: %d; sizeof(JitInstrumentation): %ld",
+ ibytes, shared_jit->num_workers, sizeof(JitInstrumentation));
+ planstate->worker_jit_instrument = palloc(ibytes);
+ MemoryContextSwitchTo(oldcontext);
+
+ memcpy(planstate->worker_jit_instrument, shared_jit, ibytes);
+}
+
+/*
* Finish parallel execution. We wait for parallel workers to finish, and
* accumulate their buffer usage.
*/
@@ -1068,6 +1139,11 @@ ExecParallelCleanup(ParallelExecutorInfo *pei)
ExecParallelRetrieveInstrumentation(pei->planstate,
pei->instrumentation);
+ /* Accumulate JIT instrumentation, if any. */
+ if (pei->jit_instrumentation)
+ ExecParallelRetrieveJitInstrumentation(pei->planstate,
+ pei->jit_instrumentation);
+
/* Free any serialized parameters. */
if (DsaPointerIsValid(pei->param_exec))
{
@@ -1274,6 +1350,7 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc)
DestReceiver *receiver;
QueryDesc *queryDesc;
SharedExecutorInstrumentation *instrumentation;
+ SharedJitInstrumentation *jit_instrumentation;
int instrument_options = 0;
void *area_space;
dsa_area *area;
@@ -1287,6 +1364,8 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc)
instrumentation = shm_toc_lookup(toc, PARALLEL_KEY_INSTRUMENTATION, true);
if (instrumentation != NULL)
instrument_options = instrumentation->instrument_options;
+ jit_instrumentation = shm_toc_lookup(toc, PARALLEL_KEY_JIT_INSTRUMENTATION,
+ true);
queryDesc = ExecParallelGetQueryDesc(toc, receiver, instrument_options);
/* Setting debug_query_string for individual workers */
@@ -1350,6 +1429,14 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc)
ExecParallelReportInstrumentation(queryDesc->planstate,
instrumentation);
+ /* Report JIT instrumentation data if any */
+ if (queryDesc->estate->es_jit && jit_instrumentation != NULL)
+ {
+ Assert(ParallelWorkerNumber < jit_instrumentation->num_workers);
+ jit_instrumentation->jit_instr[ParallelWorkerNumber] =
+ queryDesc->estate->es_jit->jit_instr;
+ }
+
/* Must do this after capturing instrumentation. */
ExecutorEnd(queryDesc);
diff --git a/src/backend/jit/jit.c b/src/backend/jit/jit.c
index 7d3883d..8c4385b 100644
--- a/src/backend/jit/jit.c
+++ b/src/backend/jit/jit.c
@@ -27,6 +27,7 @@
#include "executor/execExpr.h"
#include "jit/jit.h"
#include "miscadmin.h"
+#include "utils/memutils.h"
#include "utils/resowner_private.h"
#include "utils/fmgrprotos.h"
@@ -140,9 +141,11 @@ jit_reset_after_error(void)
void
jit_release_context(JitContext *context)
{
- if (provider_successfully_loaded)
- provider.release_context(context);
-
+ if (provider_successfully_loaded && context->provider_context)
+ {
+ provider.release_context(context->provider_context);
+ pfree(context->provider_context);
+ }
ResourceOwnerForgetJIT(context->resowner, PointerGetDatum(context));
pfree(context);
}
@@ -182,6 +185,36 @@ jit_compile_expr(struct ExprState *state)
return false;
}
+JitContext *
+jit_create_base_context(int flags)
+{
+ JitContext *context;
+
+ ResourceOwnerEnlargeJIT(CurrentResourceOwner);
+
+ context = MemoryContextAllocZero(TopMemoryContext, sizeof(JitContext));
+ context->flags = flags;
+
+ /* ensure cleanup */
+ context->resowner = CurrentResourceOwner;
+ ResourceOwnerRememberJIT(CurrentResourceOwner, PointerGetDatum(context));
+
+ return context;
+}
+
+/* Aggregate JIT instrumentation information */
+void
+InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add)
+{
+ dst->created_functions = add_size(dst->created_functions,
+ add->created_functions);
+
+ INSTR_TIME_ADD(dst->generation_counter, add->generation_counter);
+ INSTR_TIME_ADD(dst->inlining_counter, add->inlining_counter);
+ INSTR_TIME_ADD(dst->optimization_counter, add->optimization_counter);
+ INSTR_TIME_ADD(dst->emission_counter, add->emission_counter);
+}
+
static bool
file_exists(const char *name)
{
diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c
index 640c27f..6c6f078 100644
--- a/src/backend/jit/llvm/llvmjit.c
+++ b/src/backend/jit/llvm/llvmjit.c
@@ -102,7 +102,8 @@ static LLVMOrcJITStackRef llvm_opt0_orc;
static LLVMOrcJITStackRef llvm_opt3_orc;
-static void llvm_release_context(JitContext *context);
+static void *llvm_create_provider_context(JitContext *jit_context);
+static void llvm_release_context(void *context);
static void llvm_session_initialize(void);
static void llvm_shutdown(int code, Datum arg);
static void llvm_compile_module(LLVMJitContext *context);
@@ -129,28 +130,39 @@ _PG_jit_provider_init(JitProviderCallbacks *cb)
/*
* Create a context for JITing work.
*
+ * The provider first creates the base context if not already created; and then
+ * creates the provider-specific context.
* The context, including subsidiary resources, will be cleaned up either when
* the context is explicitly released, or when the lifetime of
* CurrentResourceOwner ends (usually the end of the current [sub]xact).
*/
-LLVMJitContext *
-llvm_create_context(int jitFlags)
+JitContext *
+llvm_create_context(JitContext *jit, int flags)
+{
+ if (!jit)
+ jit = jit_create_base_context(flags);
+
+ if (!jit->provider_context)
+ jit->provider_context = llvm_create_provider_context(jit);
+
+ return jit;
+}
+
+/*
+ * Create a provider-specific JIT context.
+ */
+static void *
+llvm_create_provider_context(JitContext *jit_context)
{
LLVMJitContext *context;
llvm_assert_in_fatal_section();
-
llvm_session_initialize();
- ResourceOwnerEnlargeJIT(CurrentResourceOwner);
-
- context = MemoryContextAllocZero(TopMemoryContext,
- sizeof(LLVMJitContext));
- context->base.flags = jitFlags;
+ context = MemoryContextAllocZero(TopMemoryContext, sizeof(LLVMJitContext));
- /* ensure cleanup */
- context->base.resowner = CurrentResourceOwner;
- ResourceOwnerRememberJIT(CurrentResourceOwner, PointerGetDatum(context));
+ /* Have a handle to the base context */
+ context->base = jit_context;
return context;
}
@@ -159,7 +171,7 @@ llvm_create_context(int jitFlags)
* Release resources required by one llvm context.
*/
static void
-llvm_release_context(JitContext *context)
+llvm_release_context(void *context)
{
LLVMJitContext *llvm_context = (LLVMJitContext *) context;
@@ -224,7 +236,7 @@ llvm_expand_funcname(struct LLVMJitContext *context, const char *basename)
{
Assert(context->module != NULL);
- context->base.created_functions++;
+ context->base->jit_instr.created_functions++;
/*
* Previously we used dots to separate, but turns out some tools, e.g.
@@ -422,7 +434,7 @@ llvm_optimize_module(LLVMJitContext *context, LLVMModuleRef module)
LLVMValueRef func;
int compile_optlevel;
- if (context->base.flags & PGJIT_OPT3)
+ if (context->base->flags & PGJIT_OPT3)
compile_optlevel = 3;
else
compile_optlevel = 0;
@@ -436,7 +448,7 @@ llvm_optimize_module(LLVMJitContext *context, LLVMModuleRef module)
LLVMPassManagerBuilderSetOptLevel(llvm_pmb, compile_optlevel);
llvm_fpm = LLVMCreateFunctionPassManagerForModule(module);
- if (context->base.flags & PGJIT_OPT3)
+ if (context->base->flags & PGJIT_OPT3)
{
/* TODO: Unscientifically determined threshhold */
LLVMPassManagerBuilderUseInlinerWithThreshold(llvm_pmb, 512);
@@ -469,11 +481,11 @@ llvm_optimize_module(LLVMJitContext *context, LLVMModuleRef module)
LLVMPassManagerBuilderPopulateModulePassManager(llvm_pmb,
llvm_mpm);
/* always use always-inliner pass */
- if (!(context->base.flags & PGJIT_OPT3))
+ if (!(context->base->flags & PGJIT_OPT3))
LLVMAddAlwaysInlinerPass(llvm_mpm);
/* if doing inlining, but no expensive optimization, add inlining pass */
- if (context->base.flags & PGJIT_INLINE
- && !(context->base.flags & PGJIT_OPT3))
+ if (context->base->flags & PGJIT_INLINE
+ && !(context->base->flags & PGJIT_OPT3))
LLVMAddFunctionInliningPass(llvm_mpm);
LLVMRunPassManager(llvm_mpm, context->module);
LLVMDisposePassManager(llvm_mpm);
@@ -493,18 +505,18 @@ llvm_compile_module(LLVMJitContext *context)
instr_time starttime;
instr_time endtime;
- if (context->base.flags & PGJIT_OPT3)
+ if (context->base->flags & PGJIT_OPT3)
compile_orc = llvm_opt3_orc;
else
compile_orc = llvm_opt0_orc;
/* perform inlining */
- if (context->base.flags & PGJIT_INLINE)
+ if (context->base->flags & PGJIT_INLINE)
{
INSTR_TIME_SET_CURRENT(starttime);
llvm_inline(context->module);
INSTR_TIME_SET_CURRENT(endtime);
- INSTR_TIME_ACCUM_DIFF(context->base.inlining_counter,
+ INSTR_TIME_ACCUM_DIFF(context->base->jit_instr.inlining_counter,
endtime, starttime);
}
@@ -524,7 +536,7 @@ llvm_compile_module(LLVMJitContext *context)
INSTR_TIME_SET_CURRENT(starttime);
llvm_optimize_module(context, context->module);
INSTR_TIME_SET_CURRENT(endtime);
- INSTR_TIME_ACCUM_DIFF(context->base.optimization_counter,
+ INSTR_TIME_ACCUM_DIFF(context->base->jit_instr.optimization_counter,
endtime, starttime);
if (jit_dump_bitcode)
@@ -575,7 +587,7 @@ llvm_compile_module(LLVMJitContext *context)
}
#endif
INSTR_TIME_SET_CURRENT(endtime);
- INSTR_TIME_ACCUM_DIFF(context->base.emission_counter,
+ INSTR_TIME_ACCUM_DIFF(context->base->jit_instr.emission_counter,
endtime, starttime);
context->module = NULL;
@@ -596,9 +608,9 @@ llvm_compile_module(LLVMJitContext *context)
ereport(DEBUG1,
(errmsg("time to inline: %.3fs, opt: %.3fs, emit: %.3fs",
- INSTR_TIME_GET_DOUBLE(context->base.inlining_counter),
- INSTR_TIME_GET_DOUBLE(context->base.optimization_counter),
- INSTR_TIME_GET_DOUBLE(context->base.emission_counter)),
+ INSTR_TIME_GET_DOUBLE(context->base->jit_instr.inlining_counter),
+ INSTR_TIME_GET_DOUBLE(context->base->jit_instr.optimization_counter),
+ INSTR_TIME_GET_DOUBLE(context->base->jit_instr.emission_counter)),
errhidestmt(true),
errhidecontext(true)));
}
diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c
index 0f31093..1214214 100644
--- a/src/backend/jit/llvm/llvmjit_expr.c
+++ b/src/backend/jit/llvm/llvmjit_expr.c
@@ -123,19 +123,19 @@ llvm_compile_expr(ExprState *state)
llvm_enter_fatal_on_oom();
/* get or create JIT context */
- if (parent && parent->state->es_jit)
+ if (parent)
{
- context = (LLVMJitContext *) parent->state->es_jit;
+ parent->state->es_jit = llvm_create_context(parent->state->es_jit,
+ parent->state->es_jit_flags);
+ context = parent->state->es_jit->provider_context;
}
else
{
- context = llvm_create_context(parent->state->es_jit_flags);
-
- if (parent)
- {
- parent->state->es_jit = &context->base;
- }
-
+ /*
+ * TODO: The !parent case is not handled correctly even on HEAD. Where
+ * would we get jit_flags from ?
+ */
+ context = (LLVMJitContext *) llvm_create_context(NULL, 0);
}
INSTR_TIME_SET_CURRENT(starttime);
@@ -336,7 +336,7 @@ llvm_compile_expr(ExprState *state)
* function specific to tupledesc and the exact number of
* to-be-extracted attributes.
*/
- if (desc && (context->base.flags & PGJIT_DEFORM))
+ if (desc && (context->base->flags & PGJIT_DEFORM))
{
LLVMValueRef params[1];
LLVMValueRef l_jit_deform;
@@ -2557,7 +2557,7 @@ llvm_compile_expr(ExprState *state)
llvm_leave_fatal_on_oom();
INSTR_TIME_SET_CURRENT(endtime);
- INSTR_TIME_ACCUM_DIFF(context->base.generation_counter,
+ INSTR_TIME_ACCUM_DIFF(context->base->jit_instr.generation_counter,
endtime, starttime);
return true;
diff --git a/src/include/commands/explain.h b/src/include/commands/explain.h
index 9b75baa..164cf59 100644
--- a/src/include/commands/explain.h
+++ b/src/include/commands/explain.h
@@ -81,7 +81,8 @@ extern void ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into,
extern void ExplainPrintPlan(ExplainState *es, QueryDesc *queryDesc);
extern void ExplainPrintTriggers(ExplainState *es, QueryDesc *queryDesc);
-extern void ExplainPrintJIT(ExplainState *es, QueryDesc *queryDesc);
+extern void ExplainPrintJIT(ExplainState *es, int jit_flags,
+ JitInstrumentation *jit_instr, int worker_i);
extern void ExplainQueryText(ExplainState *es, QueryDesc *queryDesc);
diff --git a/src/include/executor/execParallel.h b/src/include/executor/execParallel.h
index 626a66c..ea1991f 100644
--- a/src/include/executor/execParallel.h
+++ b/src/include/executor/execParallel.h
@@ -27,6 +27,7 @@ typedef struct ParallelExecutorInfo
ParallelContext *pcxt; /* parallel context we're using */
BufferUsage *buffer_usage; /* points to bufusage area in DSM */
SharedExecutorInstrumentation *instrumentation; /* optional */
+ SharedJitInstrumentation *jit_instrumentation; /* optional */
dsa_area *area; /* points to DSA area in DSM */
dsa_pointer param_exec; /* serialized PARAM_EXEC parameters */
bool finished; /* set true by ExecParallelFinish */
diff --git a/src/include/jit/jit.h b/src/include/jit/jit.h
index b451f40..c5ea103 100644
--- a/src/include/jit/jit.h
+++ b/src/include/jit/jit.h
@@ -23,14 +23,8 @@
#define PGJIT_EXPR (1 << 3)
#define PGJIT_DEFORM (1 << 4)
-
-typedef struct JitContext
+typedef struct JitInstrumentation
{
- /* see PGJIT_* above */
- int flags;
-
- ResourceOwner resowner;
-
/* number of emitted functions */
size_t created_functions;
@@ -45,6 +39,27 @@ typedef struct JitContext
/* accumulated time for code emission */
instr_time emission_counter;
+} JitInstrumentation;
+
+/*
+ * DSM structure for accumulating jit instrumentation of all workers.
+ *
+ * num_workers: Number of workers.
+ */
+typedef struct SharedJitInstrumentation
+{
+ int num_workers;
+ JitInstrumentation jit_instr[FLEXIBLE_ARRAY_MEMBER];
+ /* array of JitInstrumentation objects * num_workers follows */
+} SharedJitInstrumentation;
+
+typedef struct JitContext
+{
+ /* see PGJIT_* above */
+ int flags;
+ ResourceOwner resowner;
+ JitInstrumentation jit_instr;
+ void *provider_context;
} JitContext;
typedef struct JitProviderCallbacks JitProviderCallbacks;
@@ -52,13 +67,15 @@ typedef struct JitProviderCallbacks JitProviderCallbacks;
extern void _PG_jit_provider_init(JitProviderCallbacks *cb);
typedef void (*JitProviderInit) (JitProviderCallbacks *cb);
typedef void (*JitProviderResetAfterErrorCB) (void);
-typedef void (*JitProviderReleaseContextCB) (JitContext *context);
+typedef JitContext * (*JitProviderCreateContextCB) (int flags);
+typedef void (*JitProviderReleaseContextCB) (void *context);
struct ExprState;
typedef bool (*JitProviderCompileExprCB) (struct ExprState *state);
struct JitProviderCallbacks
{
JitProviderResetAfterErrorCB reset_after_error;
+ JitProviderCreateContextCB create_context;
JitProviderReleaseContextCB release_context;
JitProviderCompileExprCB compile_expr;
};
@@ -85,6 +102,8 @@ extern void jit_release_context(JitContext *context);
* not be able to perform JIT (i.e. return false).
*/
extern bool jit_compile_expr(struct ExprState *state);
+extern JitContext *jit_create_base_context(int flags);
+extern void InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add);
#endif /* JIT_H */
diff --git a/src/include/jit/llvmjit.h b/src/include/jit/llvmjit.h
index c81cff8..e9ef624 100644
--- a/src/include/jit/llvmjit.h
+++ b/src/include/jit/llvmjit.h
@@ -37,7 +37,7 @@ extern "C"
typedef struct LLVMJitContext
{
- JitContext base;
+ JitContext *base;
/* number of modules created */
size_t module_generation;
@@ -91,7 +91,7 @@ extern void llvm_leave_fatal_on_oom(void);
extern void llvm_reset_after_error(void);
extern void llvm_assert_in_fatal_section(void);
-extern LLVMJitContext *llvm_create_context(int jitFlags);
+extern JitContext *llvm_create_context(JitContext *jit, int flags);
extern LLVMModuleRef llvm_mutable_module(LLVMJitContext *context);
extern char *llvm_expand_funcname(LLVMJitContext *context, const char *basename);
extern void *llvm_get_function(LLVMJitContext *context, const char *funcname);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 687d7cd..51a3611 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -18,6 +18,7 @@
#include "access/heapam.h"
#include "access/tupconvert.h"
#include "executor/instrument.h"
+#include "jit/jit.h"
#include "lib/pairingheap.h"
#include "nodes/params.h"
#include "nodes/plannodes.h"
@@ -923,6 +924,9 @@ typedef struct PlanState
Instrumentation *instrument; /* Optional runtime stats for this node */
WorkerInstrumentation *worker_instrument; /* per-worker instrumentation */
+ /* Per-worker JIT instrumentation */
+ SharedJitInstrumentation *worker_jit_instrument;
+
/*
* Common structural data for all Plan types. These links to subsidiary
* state trees parallel links in the associated plan tree (except for the