Commit e13029a5 authored by Robert Haas's avatar Robert Haas

Provide a DSA area for all parallel queries.

This will allow future parallel query code to dynamically allocate
storage shared by all participants.

Thomas Munro, with assorted changes by me.
parent 26044384
...@@ -818,7 +818,7 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser ...@@ -818,7 +818,7 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
<tbody> <tbody>
<row> <row>
<entry morerows="57"><literal>LWLock</></entry> <entry morerows="58"><literal>LWLock</></entry>
<entry><literal>ShmemIndexLock</></entry> <entry><literal>ShmemIndexLock</></entry>
<entry>Waiting to find or allocate space in shared memory.</entry> <entry>Waiting to find or allocate space in shared memory.</entry>
</row> </row>
...@@ -1069,6 +1069,10 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser ...@@ -1069,6 +1069,10 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
<entry><literal>predicate_lock_manager</></entry> <entry><literal>predicate_lock_manager</></entry>
<entry>Waiting to add or examine predicate lock information.</entry> <entry>Waiting to add or examine predicate lock information.</entry>
</row> </row>
<row>
<entry><literal>parallel_query_dsa</></entry>
<entry>Waiting for parallel query dynamic shared memory allocation lock.</entry>
</row>
<row> <row>
<entry morerows="9"><literal>Lock</></entry> <entry morerows="9"><literal>Lock</></entry>
<entry><literal>relation</></entry> <entry><literal>relation</></entry>
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "optimizer/planner.h" #include "optimizer/planner.h"
#include "storage/spin.h" #include "storage/spin.h"
#include "tcop/tcopprot.h" #include "tcop/tcopprot.h"
#include "utils/dsa.h"
#include "utils/memutils.h" #include "utils/memutils.h"
#include "utils/snapmgr.h" #include "utils/snapmgr.h"
...@@ -47,6 +48,7 @@ ...@@ -47,6 +48,7 @@
#define PARALLEL_KEY_BUFFER_USAGE UINT64CONST(0xE000000000000003) #define PARALLEL_KEY_BUFFER_USAGE UINT64CONST(0xE000000000000003)
#define PARALLEL_KEY_TUPLE_QUEUE UINT64CONST(0xE000000000000004) #define PARALLEL_KEY_TUPLE_QUEUE UINT64CONST(0xE000000000000004)
#define PARALLEL_KEY_INSTRUMENTATION UINT64CONST(0xE000000000000005) #define PARALLEL_KEY_INSTRUMENTATION UINT64CONST(0xE000000000000005)
#define PARALLEL_KEY_DSA UINT64CONST(0xE000000000000006)
#define PARALLEL_TUPLE_QUEUE_SIZE 65536 #define PARALLEL_TUPLE_QUEUE_SIZE 65536
...@@ -345,6 +347,7 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate, int nworkers) ...@@ -345,6 +347,7 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate, int nworkers)
int param_len; int param_len;
int instrumentation_len = 0; int instrumentation_len = 0;
int instrument_offset = 0; int instrument_offset = 0;
Size dsa_minsize = dsa_minimum_size();
/* Allocate object for return value. */ /* Allocate object for return value. */
pei = palloc0(sizeof(ParallelExecutorInfo)); pei = palloc0(sizeof(ParallelExecutorInfo));
...@@ -413,6 +416,10 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate, int nworkers) ...@@ -413,6 +416,10 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate, int nworkers)
shm_toc_estimate_keys(&pcxt->estimator, 1); 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);
/* Everyone's had a chance to ask for space, so now create the DSM. */ /* Everyone's had a chance to ask for space, so now create the DSM. */
InitializeParallelDSM(pcxt); InitializeParallelDSM(pcxt);
...@@ -466,6 +473,29 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate, int nworkers) ...@@ -466,6 +473,29 @@ ExecInitParallelPlan(PlanState *planstate, EState *estate, int nworkers)
pei->instrumentation = instrumentation; pei->instrumentation = 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
* instead, then skip this.)
*/
if (pcxt->seg != NULL)
{
char *area_space;
area_space = shm_toc_allocate(pcxt->toc, dsa_minsize);
shm_toc_insert(pcxt->toc, PARALLEL_KEY_DSA, area_space);
pei->area = dsa_create_in_place(area_space, dsa_minsize,
LWTRANCHE_PARALLEL_QUERY_DSA,
"parallel_query_dsa",
pcxt->seg);
}
/*
* Make the area available to executor nodes running in the leader. See
* also ParallelQueryMain which makes it available to workers.
*/
estate->es_query_dsa = pei->area;
/* /*
* Give parallel-aware nodes a chance to initialize their shared data. * Give parallel-aware nodes a chance to initialize their shared data.
* This also initializes the elements of instrumentation->ps_instrument, * This also initializes the elements of instrumentation->ps_instrument,
...@@ -571,6 +601,11 @@ ExecParallelFinish(ParallelExecutorInfo *pei) ...@@ -571,6 +601,11 @@ ExecParallelFinish(ParallelExecutorInfo *pei)
void void
ExecParallelCleanup(ParallelExecutorInfo *pei) ExecParallelCleanup(ParallelExecutorInfo *pei)
{ {
if (pei->area != NULL)
{
dsa_detach(pei->area);
pei->area = NULL;
}
if (pei->pcxt != NULL) if (pei->pcxt != NULL)
{ {
DestroyParallelContext(pei->pcxt); DestroyParallelContext(pei->pcxt);
...@@ -728,6 +763,8 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc) ...@@ -728,6 +763,8 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc)
QueryDesc *queryDesc; QueryDesc *queryDesc;
SharedExecutorInstrumentation *instrumentation; SharedExecutorInstrumentation *instrumentation;
int instrument_options = 0; int instrument_options = 0;
void *area_space;
dsa_area *area;
/* Set up DestReceiver, SharedExecutorInstrumentation, and QueryDesc. */ /* Set up DestReceiver, SharedExecutorInstrumentation, and QueryDesc. */
receiver = ExecParallelGetReceiver(seg, toc); receiver = ExecParallelGetReceiver(seg, toc);
...@@ -739,10 +776,21 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc) ...@@ -739,10 +776,21 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc)
/* Prepare to track buffer usage during query execution. */ /* Prepare to track buffer usage during query execution. */
InstrStartParallelQuery(); InstrStartParallelQuery();
/* Start up the executor, have it run the plan, and then shut it down. */ /* Attach to the dynamic shared memory area. */
area_space = shm_toc_lookup(toc, PARALLEL_KEY_DSA);
area = dsa_attach_in_place(area_space, seg);
/* Start up the executor */
ExecutorStart(queryDesc, 0); ExecutorStart(queryDesc, 0);
/* Special executor initialization steps for parallel workers */
queryDesc->planstate->state->es_query_dsa = area;
ExecParallelInitializeWorker(queryDesc->planstate, toc); ExecParallelInitializeWorker(queryDesc->planstate, toc);
/* Run the plan */
ExecutorRun(queryDesc, ForwardScanDirection, 0L); ExecutorRun(queryDesc, ForwardScanDirection, 0L);
/* Shut down the executor */
ExecutorFinish(queryDesc); ExecutorFinish(queryDesc);
/* Report buffer usage during parallel execution. */ /* Report buffer usage during parallel execution. */
...@@ -758,6 +806,7 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc) ...@@ -758,6 +806,7 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc)
ExecutorEnd(queryDesc); ExecutorEnd(queryDesc);
/* Cleanup. */ /* Cleanup. */
dsa_detach(area);
FreeQueryDesc(queryDesc); FreeQueryDesc(queryDesc);
(*receiver->rDestroy) (receiver); (*receiver->rDestroy) (receiver);
} }
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "nodes/execnodes.h" #include "nodes/execnodes.h"
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
#include "nodes/plannodes.h" #include "nodes/plannodes.h"
#include "utils/dsa.h"
typedef struct SharedExecutorInstrumentation SharedExecutorInstrumentation; typedef struct SharedExecutorInstrumentation SharedExecutorInstrumentation;
...@@ -27,6 +28,7 @@ typedef struct ParallelExecutorInfo ...@@ -27,6 +28,7 @@ typedef struct ParallelExecutorInfo
BufferUsage *buffer_usage; BufferUsage *buffer_usage;
SharedExecutorInstrumentation *instrumentation; SharedExecutorInstrumentation *instrumentation;
shm_mq_handle **tqueue; shm_mq_handle **tqueue;
dsa_area *area;
bool finished; bool finished;
} ParallelExecutorInfo; } ParallelExecutorInfo;
......
...@@ -427,6 +427,9 @@ typedef struct EState ...@@ -427,6 +427,9 @@ typedef struct EState
HeapTuple *es_epqTuple; /* array of EPQ substitute tuples */ HeapTuple *es_epqTuple; /* array of EPQ substitute tuples */
bool *es_epqTupleSet; /* true if EPQ tuple is provided */ bool *es_epqTupleSet; /* true if EPQ tuple is provided */
bool *es_epqScanDone; /* true if EPQ tuple has been fetched */ bool *es_epqScanDone; /* true if EPQ tuple has been fetched */
/* The per-query shared memory area to use for parallel execution. */
struct dsa_area *es_query_dsa;
} EState; } EState;
......
...@@ -210,6 +210,7 @@ typedef enum BuiltinTrancheIds ...@@ -210,6 +210,7 @@ typedef enum BuiltinTrancheIds
LWTRANCHE_BUFFER_MAPPING, LWTRANCHE_BUFFER_MAPPING,
LWTRANCHE_LOCK_MANAGER, LWTRANCHE_LOCK_MANAGER,
LWTRANCHE_PREDICATE_LOCK_MANAGER, LWTRANCHE_PREDICATE_LOCK_MANAGER,
LWTRANCHE_PARALLEL_QUERY_DSA,
LWTRANCHE_FIRST_USER_DEFINED LWTRANCHE_FIRST_USER_DEFINED
} BuiltinTrancheIds; } BuiltinTrancheIds;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment