Skip to content

Commit fc83bed

Browse files
author
Alena Rybakina
committed
Add hierarchical memory context for saving datas not
to use postgres memory contexts except situation when AQO prediction which is passed on to the optimizer. We add three additional memory context for managing memory. AQOMemoryContext is renamed as AQOCacheMemCtx and containe as in the previous time environment data. During predict for plan nodes all of palloc is saved into AQO Predict Memory Context and clean up in the execution stage of query. After executing query we collect some long lived information until it is put into AQO knowledge table. All of them are saved in AQO Learn Memory Context. During these stages we calculates hashes from having got clause, selectivity arrays and relid lists. These tactical information is short-lived, so we save it in the AQO Utility Memory Context. We clean up Utility Memory Context inside calculated function or immediately after her having completed.
1 parent ef6397d commit fc83bed

11 files changed

+171
-138
lines changed

‎aqo.c

+51-7
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,23 @@ double log_selectivity_lower_bound = -30;
8181
* Currently we use it only to store query_text string which is initialized
8282
* after a query parsing and is used during the query planning.
8383
*/
84-
MemoryContext AQOMemoryContext;
85-
MemoryContext AQO_cache_mem_ctx;
84+
8685
QueryContextData query_context;
86+
87+
MemoryContext AQOTopMemCtx = NULL;
88+
89+
/* Is released at the end of transaction */
90+
MemoryContext AQOCacheMemCtx = NULL;
91+
92+
/* Should be released in-place, just after a huge calculation */
93+
MemoryContext AQOUtilityMemCtx = NULL;
94+
95+
/* Is released at the end of planning */
96+
MemoryContext AQOPredictMemCtx = NULL;
97+
98+
/* Is released at the end of learning */
99+
MemoryContext AQOLearnMemCtx = NULL;
100+
87101
/* Additional plan info */
88102
int njoins;
89103

@@ -119,7 +133,7 @@ aqo_free_callback(ResourceReleasePhase phase,
119133

120134
if (isTopLevel)
121135
{
122-
list_free_deep(cur_classes);
136+
MemoryContextReset(AQOCacheMemCtx);
123137
cur_classes = NIL;
124138
}
125139
}
@@ -320,12 +334,42 @@ _PG_init(void)
320334
shmem_request_hook = aqo_shmem_request;
321335

322336
init_deactivated_queries_storage();
323-
AQOMemoryContext = AllocSetContextCreate(TopMemoryContext,
324-
"AQOMemoryContext",
337+
338+
/*
339+
* Create own Top memory Context for reporting AQO memory in the future.
340+
*/
341+
AQOTopMemCtx = AllocSetContextCreate(TopMemoryContext,
342+
"AQOTopMemoryContext",
325343
ALLOCSET_DEFAULT_SIZES);
326-
AQO_cache_mem_ctx = AllocSetContextCreate(TopMemoryContext,
327-
"AQO_cache_mem_ctx",
344+
/*
345+
* AQO Cache Memory Context containe environment data.
346+
*/
347+
AQOCacheMemCtx = AllocSetContextCreate(AQOTopMemCtx,
348+
"AQOCacheMemCtx",
328349
ALLOCSET_DEFAULT_SIZES);
350+
/*
351+
* AQOUtilityMemoryContext containe short-lived information which
352+
* is appeared from having got clause, selectivity arrays and relid lists
353+
* while calculating hashes. It clean up inside calculated
354+
* function or immediately after her having completed.
355+
*/
356+
AQOUtilityMemCtx = AllocSetContextCreate(AQOTopMemCtx,
357+
"AQOUtilityMemoryContext",
358+
ALLOCSET_DEFAULT_SIZES);
359+
/*
360+
* AQOPredictMemoryContext save necessary information for making predict of plan nodes
361+
* and clean up in the execution stage of query.
362+
*/
363+
AQOPredictMemCtx = AllocSetContextCreate(AQOTopMemCtx,
364+
"AQOPredictMemoryContext",
365+
ALLOCSET_DEFAULT_SIZES);
366+
/*
367+
* AQOLearnMemoryContext save necessary information for writing down to AQO knowledge table
368+
* and clean up after doing this operation.
369+
*/
370+
AQOLearnMemCtx = AllocSetContextCreate(AQOTopMemCtx,
371+
"AQOLearnMemoryContext",
372+
ALLOCSET_DEFAULT_SIZES);
329373
RegisterResourceReleaseCallback(aqo_free_callback, NULL);
330374
RegisterAQOPlanNodeMethods();
331375

‎aqo.h

+6-3
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,12 @@ extern double log_selectivity_lower_bound;
221221
extern QueryContextData query_context;
222222
extern int njoins;
223223

224-
/* Memory context for long-live data */
225-
extern MemoryContext AQOMemoryContext;
226-
extern MemoryContext AQO_cache_mem_ctx;
224+
/* AQO Memory contexts */
225+
extern MemoryContext AQOTopMemCtx;
226+
extern MemoryContext AQOCacheMemCtx;
227+
extern MemoryContext AQOUtilityMemCtx;
228+
extern MemoryContext AQOPredictMemCtx;
229+
extern MemoryContext AQOLearnMemCtx;
227230

228231
/* Saved hook values in case of unload */
229232
extern post_parse_analyze_hook_type prev_post_parse_analyze_hook;

‎cardinality_estimation.c

-3
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ predict_debug_output(List *clauses, List *selectivities,
5252

5353
appendStringInfo(&debug_str, "}, result: %lf", result);
5454
elog(DEBUG1, "Prediction: %s", debug_str.data);
55-
pfree(debug_str.data);
5655
}
5756
#endif
5857

@@ -104,8 +103,6 @@ predict_for_relation(List *clauses, List *selectivities, List *relsigns,
104103
#ifdef AQO_DEBUG_PRINT
105104
predict_debug_output(clauses, selectivities, relsigns, *fss, result);
106105
#endif
107-
pfree(features);
108-
OkNNr_free(data);
109106

110107
if (result < 0)
111108
return -1;

‎cardinality_hooks.c

+32-34
Original file line numberDiff line numberDiff line change
@@ -144,20 +144,21 @@ aqo_set_baserel_rows_estimate(PlannerInfo *root, RelOptInfo *rel)
144144
List *selectivities = NULL;
145145
List *clauses;
146146
int fss = 0;
147+
MemoryContext old_ctx_m;
147148

148149
if (IsQueryDisabled())
149150
/* Fast path. */
150151
goto default_estimator;
151152

153+
old_ctx_m = MemoryContextSwitchTo(AQOPredictMemCtx);
154+
152155
if (query_context.use_aqo || query_context.learn_aqo)
153156
selectivities = get_selectivities(root, rel->baserestrictinfo, 0,
154157
JOIN_INNER, NULL);
155158

156159
if (!query_context.use_aqo)
157160
{
158-
if (query_context.learn_aqo)
159-
list_free_deep(selectivities);
160-
161+
MemoryContextSwitchTo(old_ctx_m);
161162
goto default_estimator;
162163
}
163164

@@ -175,10 +176,8 @@ aqo_set_baserel_rows_estimate(PlannerInfo *root, RelOptInfo *rel)
175176
&fss);
176177
rel->fss_hash = fss;
177178

178-
list_free(rels.hrels);
179-
list_free(rels.signatures);
180-
list_free_deep(selectivities);
181-
list_free(clauses);
179+
/* Return to the caller's memory context. */
180+
MemoryContextSwitchTo(old_ctx_m);
182181

183182
if (predicted >= 0)
184183
{
@@ -225,14 +224,16 @@ aqo_get_parameterized_baserel_size(PlannerInfo *root,
225224
int *eclass_hash;
226225
int current_hash;
227226
int fss = 0;
227+
MemoryContext oldctx;
228228

229229
if (IsQueryDisabled())
230230
/* Fast path */
231231
goto default_estimator;
232232

233+
oldctx = MemoryContextSwitchTo(AQOPredictMemCtx);
234+
233235
if (query_context.use_aqo || query_context.learn_aqo)
234236
{
235-
MemoryContext old_ctx_m;
236237

237238
selectivities = list_concat(
238239
get_selectivities(root, param_clauses, rel->relid,
@@ -248,8 +249,6 @@ aqo_get_parameterized_baserel_size(PlannerInfo *root,
248249
rte = planner_rt_fetch(rel->relid, root);
249250
get_eclasses(allclauses, &nargs, &args_hash, &eclass_hash);
250251

251-
old_ctx_m = MemoryContextSwitchTo(AQO_cache_mem_ctx);
252-
253252
forboth(l, allclauses, l2, selectivities)
254253
{
255254
current_hash = get_clause_hash(
@@ -258,19 +257,11 @@ aqo_get_parameterized_baserel_size(PlannerInfo *root,
258257
cache_selectivity(current_hash, rel->relid, rte->relid,
259258
*((double *) lfirst(l2)));
260259
}
261-
262-
MemoryContextSwitchTo(old_ctx_m);
263-
pfree(args_hash);
264-
pfree(eclass_hash);
265260
}
266261

267262
if (!query_context.use_aqo)
268263
{
269-
if (query_context.learn_aqo)
270-
{
271-
list_free_deep(selectivities);
272-
list_free(allclauses);
273-
}
264+
MemoryContextSwitchTo(oldctx);
274265

275266
goto default_estimator;
276267
}
@@ -284,8 +275,9 @@ aqo_get_parameterized_baserel_size(PlannerInfo *root,
284275
}
285276

286277
predicted = predict_for_relation(allclauses, selectivities, rels.signatures, &fss);
287-
list_free(rels.hrels);
288-
list_free(rels.signatures);
278+
279+
/* Return to the caller's memory context */
280+
MemoryContextSwitchTo(oldctx);
289281

290282
predicted_ppi_rows = predicted;
291283
fss_ppi_hash = fss;
@@ -319,20 +311,20 @@ aqo_set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel,
319311
List *outer_selectivities;
320312
List *current_selectivities = NULL;
321313
int fss = 0;
314+
MemoryContext old_ctx_m;
322315

323316
if (IsQueryDisabled())
324317
/* Fast path */
325318
goto default_estimator;
326319

320+
old_ctx_m = MemoryContextSwitchTo(AQOPredictMemCtx);
321+
327322
if (query_context.use_aqo || query_context.learn_aqo)
328323
current_selectivities = get_selectivities(root, restrictlist, 0,
329324
sjinfo->jointype, sjinfo);
330-
331325
if (!query_context.use_aqo)
332326
{
333-
if (query_context.learn_aqo)
334-
list_free_deep(current_selectivities);
335-
327+
MemoryContextSwitchTo(old_ctx_m);
336328
goto default_estimator;
337329
}
338330

@@ -349,8 +341,9 @@ aqo_set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel,
349341

350342
predicted = predict_for_relation(allclauses, selectivities, rels.signatures,
351343
&fss);
352-
list_free(rels.hrels);
353-
list_free(rels.signatures);
344+
345+
/* Return to the caller's memory context */
346+
MemoryContextSwitchTo(old_ctx_m);
354347

355348
rel->fss_hash = fss;
356349

@@ -391,20 +384,21 @@ aqo_get_parameterized_joinrel_size(PlannerInfo *root,
391384
List *outer_selectivities;
392385
List *current_selectivities = NULL;
393386
int fss = 0;
387+
MemoryContext old_ctx_m;
394388

395389
if (IsQueryDisabled())
396390
/* Fast path */
397391
goto default_estimator;
398392

393+
old_ctx_m = MemoryContextSwitchTo(AQOPredictMemCtx);
394+
399395
if (query_context.use_aqo || query_context.learn_aqo)
400396
current_selectivities = get_selectivities(root, clauses, 0,
401397
sjinfo->jointype, sjinfo);
402398

403399
if (!query_context.use_aqo)
404400
{
405-
if (query_context.learn_aqo)
406-
list_free_deep(current_selectivities);
407-
401+
MemoryContextSwitchTo(old_ctx_m);
408402
goto default_estimator;
409403
}
410404

@@ -419,8 +413,8 @@ aqo_get_parameterized_joinrel_size(PlannerInfo *root,
419413

420414
predicted = predict_for_relation(allclauses, selectivities, rels.signatures,
421415
&fss);
422-
list_free(rels.hrels);
423-
list_free(rels.signatures);
416+
/* Return to the caller's memory context */
417+
MemoryContextSwitchTo(old_ctx_m);
424418

425419
predicted_ppi_rows = predicted;
426420
fss_ppi_hash = fss;
@@ -455,8 +449,6 @@ predict_num_groups(PlannerInfo *root, Path *subpath, List *group_exprs,
455449
clauses = get_path_clauses(subpath, root, &selectivities);
456450
(void) predict_for_relation(clauses, selectivities, rels.signatures,
457451
&child_fss);
458-
list_free(rels.hrels);
459-
list_free(rels.signatures);
460452
}
461453

462454
*fss = get_grouped_exprs_hash(child_fss, group_exprs);
@@ -477,6 +469,7 @@ aqo_estimate_num_groups_hook(PlannerInfo *root, List *groupExprs,
477469
{
478470
int fss;
479471
double predicted;
472+
MemoryContext old_ctx_m;
480473

481474
if (!query_context.use_aqo)
482475
goto default_estimator;
@@ -495,12 +488,15 @@ aqo_estimate_num_groups_hook(PlannerInfo *root, List *groupExprs,
495488
if (groupExprs == NIL)
496489
return 1.0;
497490

491+
old_ctx_m = MemoryContextSwitchTo(AQOPredictMemCtx);
492+
498493
predicted = predict_num_groups(root, subpath, groupExprs, &fss);
499494
if (predicted > 0.)
500495
{
501496
grouped_rel->predicted_cardinality = predicted;
502497
grouped_rel->rows = predicted;
503498
grouped_rel->fss_hash = fss;
499+
MemoryContextSwitchTo(old_ctx_m);
504500
return predicted;
505501
}
506502
else
@@ -510,6 +506,8 @@ aqo_estimate_num_groups_hook(PlannerInfo *root, List *groupExprs,
510506
*/
511507
grouped_rel->predicted_cardinality = -1;
512508

509+
MemoryContextSwitchTo(old_ctx_m);
510+
513511
default_estimator:
514512
return default_estimate_num_groups(root, groupExprs, subpath, grouped_rel,
515513
pgset, estinfo);

0 commit comments

Comments
 (0)