PostgreSQL Source Code  git master
nodeResultCache.h File Reference
#include "access/parallel.h"
#include "nodes/execnodes.h"
Include dependency graph for nodeResultCache.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

ResultCacheStateExecInitResultCache (ResultCache *node, EState *estate, int eflags)
 
void ExecEndResultCache (ResultCacheState *node)
 
void ExecReScanResultCache (ResultCacheState *node)
 
double ExecEstimateCacheEntryOverheadBytes (double ntuples)
 
void ExecResultCacheEstimate (ResultCacheState *node, ParallelContext *pcxt)
 
void ExecResultCacheInitializeDSM (ResultCacheState *node, ParallelContext *pcxt)
 
void ExecResultCacheInitializeWorker (ResultCacheState *node, ParallelWorkerContext *pwcxt)
 
void ExecResultCacheRetrieveInstrumentation (ResultCacheState *node)
 

Function Documentation

◆ ExecEndResultCache()

void ExecEndResultCache ( ResultCacheState node)

Definition at line 943 of file nodeResultCache.c.

References Assert, CACHE_TUPLE_BYTES, EMPTY_ENTRY_MEMORY_BYTES, ExecClearTuple(), ExecEndNode(), ExecFreeExprContext(), ResultCacheState::hashtable, i, IsParallelWorker, ResultCacheInstrumentation::mem_peak, ResultCacheState::mem_used, MemoryContextDelete(), ResultCacheTuple::next, outerPlanState, ParallelWorkerNumber, ScanState::ps, PlanState::ps_ResultTupleSlot, ResultCacheState::shared_info, SharedResultCacheInfo::sinstrument, ResultCacheState::ss, ScanState::ss_ScanTupleSlot, ResultCacheState::stats, ResultCacheState::tableContext, and ResultCacheEntry::tuplehead.

Referenced by ExecEndNode().

944 {
945 #ifdef USE_ASSERT_CHECKING
946  /* Validate the memory accounting code is correct in assert builds. */
947  {
948  int count;
949  uint64 mem = 0;
950  resultcache_iterator i;
951  ResultCacheEntry *entry;
952 
953  resultcache_start_iterate(node->hashtable, &i);
954 
955  count = 0;
956  while ((entry = resultcache_iterate(node->hashtable, &i)) != NULL)
957  {
958  ResultCacheTuple *tuple = entry->tuplehead;
959 
960  mem += EMPTY_ENTRY_MEMORY_BYTES(entry);
961  while (tuple != NULL)
962  {
963  mem += CACHE_TUPLE_BYTES(tuple);
964  tuple = tuple->next;
965  }
966  count++;
967  }
968 
969  Assert(count == node->hashtable->members);
970  Assert(mem == node->mem_used);
971  }
972 #endif
973 
974  /*
975  * When ending a parallel worker, copy the statistics gathered by the
976  * worker back into shared memory so that it can be picked up by the main
977  * process to report in EXPLAIN ANALYZE.
978  */
979  if (node->shared_info != NULL && IsParallelWorker())
980  {
982 
983  /* Make mem_peak available for EXPLAIN */
984  if (node->stats.mem_peak == 0)
985  node->stats.mem_peak = node->mem_used;
986 
987  Assert(ParallelWorkerNumber <= node->shared_info->num_workers);
989  memcpy(si, &node->stats, sizeof(ResultCacheInstrumentation));
990  }
991 
992  /* Remove the cache context */
994 
996  /* must drop pointer to cache result tuple */
998 
999  /*
1000  * free exprcontext
1001  */
1002  ExecFreeExprContext(&node->ss.ps);
1003 
1004  /*
1005  * shut down the subplan
1006  */
1007  ExecEndNode(outerPlanState(node));
1008 }
MemoryContext tableContext
Definition: execnodes.h:2100
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:425
ScanState ss
Definition: execnodes.h:2086
ResultCacheTuple * tuplehead
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:556
struct resultcache_hash * hashtable
Definition: execnodes.h:2089
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1379
SharedResultCacheInfo * shared_info
Definition: execnodes.h:2111
ResultCacheInstrumentation sinstrument[FLEXIBLE_ARRAY_MEMBER]
Definition: execnodes.h:2074
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:650
ResultCacheInstrumentation stats
Definition: execnodes.h:2110
PlanState ps
Definition: execnodes.h:1376
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1003
#define outerPlanState(node)
Definition: execnodes.h:1061
#define EMPTY_ENTRY_MEMORY_BYTES(e)
int ParallelWorkerNumber
Definition: parallel.c:112
#define IsParallelWorker()
Definition: parallel.h:61
#define CACHE_TUPLE_BYTES(t)
#define Assert(condition)
Definition: c.h:804
int i
struct ResultCacheTuple * next

◆ ExecEstimateCacheEntryOverheadBytes()

double ExecEstimateCacheEntryOverheadBytes ( double  ntuples)

Definition at line 1037 of file nodeResultCache.c.

Referenced by cost_resultcache_rescan().

1038 {
1039  return sizeof(ResultCacheEntry) + sizeof(ResultCacheKey) +
1040  sizeof(ResultCacheTuple) * ntuples;
1041 }
struct ResultCacheEntry ResultCacheEntry
struct ResultCacheTuple ResultCacheTuple

◆ ExecInitResultCache()

ResultCacheState* ExecInitResultCache ( ResultCache node,
EState estate,
int  eflags 
)

Definition at line 825 of file nodeResultCache.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, build_hash_table(), ResultCacheState::cache_eq_expr, ResultCache::collations, ResultCacheState::collations, CurrentMemoryContext, dlist_init(), elog, ERROR, ResultCache::est_entries, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, ExecAssignExprContext(), ExecBuildParamSetEqual(), ExecCreateScanSlotFromOuterPlan(), ExecInitExpr(), ExecInitNode(), ExecInitResultTupleSlotTL(), PlanState::ExecProcNode, ExecResultCache(), ExecTypeFromExprList(), fmgr_info(), get_hash_mem(), get_op_hash_functions(), get_opcode(), ResultCacheState::hashfunctions, ResultCacheState::hashkeydesc, ResultCache::hashOperators, i, list_nth(), makeNode, MakeSingleTupleTableSlot(), ResultCacheState::nkeys, ResultCache::numKeys, outerPlan, outerPlanState, palloc(), ResultCache::param_exprs, ResultCacheState::param_exprs, pfree(), PlanState::plan, ResultCacheState::probeslot, ScanState::ps, PlanState::ps_ProjInfo, RC_CACHE_LOOKUP, ResultCacheState::rc_status, ResultCache::singlerow, ResultCacheState::ss, PlanState::state, ResultCacheState::tableslot, TTSOpsMinimalTuple, and TTSOpsVirtual.

Referenced by ExecInitNode().

826 {
828  Plan *outerNode;
829  int i;
830  int nkeys;
831  Oid *eqfuncoids;
832 
833  /* check for unsupported flags */
834  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
835 
836  rcstate->ss.ps.plan = (Plan *) node;
837  rcstate->ss.ps.state = estate;
838  rcstate->ss.ps.ExecProcNode = ExecResultCache;
839 
840  /*
841  * Miscellaneous initialization
842  *
843  * create expression context for node
844  */
845  ExecAssignExprContext(estate, &rcstate->ss.ps);
846 
847  outerNode = outerPlan(node);
848  outerPlanState(rcstate) = ExecInitNode(outerNode, estate, eflags);
849 
850  /*
851  * Initialize return slot and type. No need to initialize projection info
852  * because this node doesn't do projections.
853  */
855  rcstate->ss.ps.ps_ProjInfo = NULL;
856 
857  /*
858  * Initialize scan slot and type.
859  */
861 
862  /*
863  * Set the state machine to lookup the cache. We won't find anything
864  * until we cache something, but this saves a special case to create the
865  * first entry.
866  */
867  rcstate->rc_status = RC_CACHE_LOOKUP;
868 
869  rcstate->nkeys = nkeys = node->numKeys;
870  rcstate->hashkeydesc = ExecTypeFromExprList(node->param_exprs);
871  rcstate->tableslot = MakeSingleTupleTableSlot(rcstate->hashkeydesc,
873  rcstate->probeslot = MakeSingleTupleTableSlot(rcstate->hashkeydesc,
874  &TTSOpsVirtual);
875 
876  rcstate->param_exprs = (ExprState **) palloc(nkeys * sizeof(ExprState *));
877  rcstate->collations = node->collations; /* Just point directly to the plan
878  * data */
879  rcstate->hashfunctions = (FmgrInfo *) palloc(nkeys * sizeof(FmgrInfo));
880 
881  eqfuncoids = palloc(nkeys * sizeof(Oid));
882 
883  for (i = 0; i < nkeys; i++)
884  {
885  Oid hashop = node->hashOperators[i];
886  Oid left_hashfn;
887  Oid right_hashfn;
888  Expr *param_expr = (Expr *) list_nth(node->param_exprs, i);
889 
890  if (!get_op_hash_functions(hashop, &left_hashfn, &right_hashfn))
891  elog(ERROR, "could not find hash function for hash operator %u",
892  hashop);
893 
894  fmgr_info(left_hashfn, &rcstate->hashfunctions[i]);
895 
896  rcstate->param_exprs[i] = ExecInitExpr(param_expr, (PlanState *) rcstate);
897  eqfuncoids[i] = get_opcode(hashop);
898  }
899 
902  &TTSOpsVirtual,
903  eqfuncoids,
904  node->collations,
905  node->param_exprs,
906  (PlanState *) rcstate);
907 
908  pfree(eqfuncoids);
909  rcstate->mem_used = 0;
910 
911  /* Limit the total memory consumed by the cache to this */
912  rcstate->mem_limit = get_hash_mem() * 1024L;
913 
914  /* A memory context dedicated for the cache */
916  "ResultCacheHashTable",
918 
919  dlist_init(&rcstate->lru_list);
920  rcstate->last_tuple = NULL;
921  rcstate->entry = NULL;
922 
923  /*
924  * Mark if we can assume the cache entry is completed after we get the
925  * first record for it. Some callers might not call us again after
926  * getting the first match. e.g. A join operator performing a unique join
927  * is able to skip to the next outer tuple after getting the first
928  * matching inner tuple. In this case, the cache entry is complete after
929  * getting the first tuple. This allows us to mark it as so.
930  */
931  rcstate->singlerow = node->singlerow;
932 
933  /* Zero the statistics counters */
934  memset(&rcstate->stats, 0, sizeof(ResultCacheInstrumentation));
935 
936  /* Allocate and set up the actual cache */
937  build_hash_table(rcstate, node->est_entries);
938 
939  return rcstate;
940 }
MemoryContext tableContext
Definition: execnodes.h:2100
uint32 est_entries
Definition: plannodes.h:799
Definition: fmgr.h:56
#define AllocSetContextCreate
Definition: memutils.h:173
bool get_op_hash_functions(Oid opno, RegProcedure *lhs_procno, RegProcedure *rhs_procno)
Definition: lsyscache.c:508
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:1005
ScanState ss
Definition: execnodes.h:2086
TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1238
TupleTableSlot * tableslot
Definition: execnodes.h:2091
ExprState * ExecBuildParamSetEqual(TupleDesc desc, const TupleTableSlotOps *lops, const TupleTableSlotOps *rops, const Oid *eqfunctions, const Oid *collations, const List *param_exprs, PlanState *parent)
Definition: execExpr.c:3840
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
FmgrInfo * hashfunctions
Definition: execnodes.h:2096
EState * state
Definition: execnodes.h:967
unsigned int Oid
Definition: postgres_ext.h:31
Oid * hashOperators
Definition: plannodes.h:793
ResultCacheInstrumentation stats
Definition: execnodes.h:2110
PlanState ps
Definition: execnodes.h:1376
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ERROR
Definition: elog.h:46
static void * list_nth(const List *list, int n)
Definition: pg_list.h:278
TupleDesc hashkeydesc
Definition: execnodes.h:2090
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition: fmgr.c:126
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:195
#define EXEC_FLAG_BACKWARD
Definition: executor.h:58
#define outerPlanState(node)
Definition: execnodes.h:1061
ExprState ** param_exprs
Definition: execnodes.h:2094
dlist_head lru_list
Definition: execnodes.h:2101
bool singlerow
Definition: plannodes.h:796
struct ResultCacheEntry * entry
Definition: execnodes.h:2106
struct ResultCacheTuple * last_tuple
Definition: execnodes.h:2102
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
#define outerPlan(node)
Definition: plannodes.h:171
#define RC_CACHE_LOOKUP
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:971
Plan * plan
Definition: execnodes.h:965
static void dlist_init(dlist_head *head)
Definition: ilist.h:278
RegProcedure get_opcode(Oid opno)
Definition: lsyscache.c:1256
#define makeNode(_type_)
Definition: nodes.h:587
#define Assert(condition)
Definition: c.h:804
static void build_hash_table(ResultCacheState *rcstate, uint32 size)
#define EXEC_FLAG_MARK
Definition: executor.h:59
Oid * collations
Definition: plannodes.h:794
ExprState * cache_eq_expr
Definition: execnodes.h:2093
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:480
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1799
List * param_exprs
Definition: plannodes.h:795
TupleDesc ExecTypeFromExprList(List *exprList)
Definition: execTuples.c:1997
void * palloc(Size size)
Definition: mcxt.c:1062
static TupleTableSlot * ExecResultCache(PlanState *pstate)
#define elog(elevel,...)
Definition: elog.h:232
int i
TupleTableSlot * probeslot
Definition: execnodes.h:2092
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:123
void ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate, const TupleTableSlotOps *tts_ops)
Definition: execUtils.c:682
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:141
const TupleTableSlotOps TTSOpsMinimalTuple
Definition: execTuples.c:85
int get_hash_mem(void)
Definition: nodeHash.c:3389

◆ ExecReScanResultCache()

void ExecReScanResultCache ( ResultCacheState node)

Definition at line 1011 of file nodeResultCache.c.

References PlanState::chgParam, ResultCacheState::entry, ExecReScan(), ResultCacheState::last_tuple, outerPlan, outerPlanState, RC_CACHE_LOOKUP, and ResultCacheState::rc_status.

Referenced by ExecReScan().

1012 {
1014 
1015  /* Mark that we must lookup the cache for a new set of parameters */
1016  node->rc_status = RC_CACHE_LOOKUP;
1017 
1018  /* nullify pointers used for the last scan */
1019  node->entry = NULL;
1020  node->last_tuple = NULL;
1021 
1022  /*
1023  * if chgParam of subnode is not null then plan will be re-scanned by
1024  * first ExecProcNode.
1025  */
1026  if (outerPlan->chgParam == NULL)
1027  ExecReScan(outerPlan);
1028 
1029 }
void ExecReScan(PlanState *node)
Definition: execAmi.c:78
#define outerPlanState(node)
Definition: execnodes.h:1061
struct ResultCacheEntry * entry
Definition: execnodes.h:2106
struct ResultCacheTuple * last_tuple
Definition: execnodes.h:2102
Bitmapset * chgParam
Definition: execnodes.h:997
#define outerPlan(node)
Definition: plannodes.h:171
#define RC_CACHE_LOOKUP

◆ ExecResultCacheEstimate()

void ExecResultCacheEstimate ( ResultCacheState node,
ParallelContext pcxt 
)

Definition at line 1055 of file nodeResultCache.c.

References add_size(), ParallelContext::estimator, PlanState::instrument, mul_size(), ParallelContext::nworkers, offsetof, ScanState::ps, shm_toc_estimate_chunk, shm_toc_estimate_keys, and ResultCacheState::ss.

Referenced by ExecParallelEstimate().

1056 {
1057  Size size;
1058 
1059  /* don't need this if not instrumenting or no workers */
1060  if (!node->ss.ps.instrument || pcxt->nworkers == 0)
1061  return;
1062 
1063  size = mul_size(pcxt->nworkers, sizeof(ResultCacheInstrumentation));
1064  size = add_size(size, offsetof(SharedResultCacheInfo, sinstrument));
1065  shm_toc_estimate_chunk(&pcxt->estimator, size);
1066  shm_toc_estimate_keys(&pcxt->estimator, 1);
1067 }
Instrumentation * instrument
Definition: execnodes.h:975
ScanState ss
Definition: execnodes.h:2086
shm_toc_estimator estimator
Definition: parallel.h:42
#define shm_toc_estimate_chunk(e, sz)
Definition: shm_toc.h:51
PlanState ps
Definition: execnodes.h:1376
Size mul_size(Size s1, Size s2)
Definition: shmem.c:519
Size add_size(Size s1, Size s2)
Definition: shmem.c:502
size_t Size
Definition: c.h:540
#define shm_toc_estimate_keys(e, cnt)
Definition: shm_toc.h:53
#define offsetof(type, field)
Definition: c.h:727

◆ ExecResultCacheInitializeDSM()

void ExecResultCacheInitializeDSM ( ResultCacheState node,
ParallelContext pcxt 
)

Definition at line 1076 of file nodeResultCache.c.

References PlanState::instrument, SharedResultCacheInfo::num_workers, ParallelContext::nworkers, offsetof, PlanState::plan, Plan::plan_node_id, ScanState::ps, ResultCacheState::shared_info, shm_toc_allocate(), shm_toc_insert(), ResultCacheState::ss, and ParallelContext::toc.

Referenced by ExecParallelInitializeDSM().

1077 {
1078  Size size;
1079 
1080  /* don't need this if not instrumenting or no workers */
1081  if (!node->ss.ps.instrument || pcxt->nworkers == 0)
1082  return;
1083 
1084  size = offsetof(SharedResultCacheInfo, sinstrument)
1085  + pcxt->nworkers * sizeof(ResultCacheInstrumentation);
1086  node->shared_info = shm_toc_allocate(pcxt->toc, size);
1087  /* ensure any unfilled slots will contain zeroes */
1088  memset(node->shared_info, 0, size);
1089  node->shared_info->num_workers = pcxt->nworkers;
1090  shm_toc_insert(pcxt->toc, node->ss.ps.plan->plan_node_id,
1091  node->shared_info);
1092 }
Instrumentation * instrument
Definition: execnodes.h:975
ScanState ss
Definition: execnodes.h:2086
struct ResultCacheInstrumentation ResultCacheInstrumentation
int plan_node_id
Definition: plannodes.h:140
SharedResultCacheInfo * shared_info
Definition: execnodes.h:2111
PlanState ps
Definition: execnodes.h:1376
Plan * plan
Definition: execnodes.h:965
size_t Size
Definition: c.h:540
void * shm_toc_allocate(shm_toc *toc, Size nbytes)
Definition: shm_toc.c:88
void shm_toc_insert(shm_toc *toc, uint64 key, void *address)
Definition: shm_toc.c:171
#define offsetof(type, field)
Definition: c.h:727
shm_toc * toc
Definition: parallel.h:45

◆ ExecResultCacheInitializeWorker()

void ExecResultCacheInitializeWorker ( ResultCacheState node,
ParallelWorkerContext pwcxt 
)

Definition at line 1101 of file nodeResultCache.c.

References PlanState::plan, Plan::plan_node_id, ScanState::ps, ResultCacheState::shared_info, shm_toc_lookup(), ResultCacheState::ss, and ParallelWorkerContext::toc.

Referenced by ExecParallelInitializeWorker().

1102 {
1103  node->shared_info =
1104  shm_toc_lookup(pwcxt->toc, node->ss.ps.plan->plan_node_id, true);
1105 }
ScanState ss
Definition: execnodes.h:2086
int plan_node_id
Definition: plannodes.h:140
SharedResultCacheInfo * shared_info
Definition: execnodes.h:2111
PlanState ps
Definition: execnodes.h:1376
Plan * plan
Definition: execnodes.h:965
void * shm_toc_lookup(shm_toc *toc, uint64 key, bool noError)
Definition: shm_toc.c:232

◆ ExecResultCacheRetrieveInstrumentation()

void ExecResultCacheRetrieveInstrumentation ( ResultCacheState node)

Definition at line 1114 of file nodeResultCache.c.

References SharedResultCacheInfo::num_workers, offsetof, palloc(), and ResultCacheState::shared_info.

Referenced by ExecParallelRetrieveInstrumentation().

1115 {
1116  Size size;
1118 
1119  if (node->shared_info == NULL)
1120  return;
1121 
1122  size = offsetof(SharedResultCacheInfo, sinstrument)
1124  si = palloc(size);
1125  memcpy(si, node->shared_info, size);
1126  node->shared_info = si;
1127 }
struct ResultCacheInstrumentation ResultCacheInstrumentation
SharedResultCacheInfo * shared_info
Definition: execnodes.h:2111
size_t Size
Definition: c.h:540
void * palloc(Size size)
Definition: mcxt.c:1062
#define offsetof(type, field)
Definition: c.h:727