Skip to content

Commit b011f95

Browse files
a.pervushinadanolivo
a.pervushina
authored andcommitted
Hide the AQO Statement Timeout feature under a GUC.
Use aqo.learn_statement_timeout to enable this feature. On more function here is to do cleanup on this cache and memory context.
1 parent 8ec4463 commit b011f95

File tree

5 files changed

+60
-5
lines changed

5 files changed

+60
-5
lines changed

aqo.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,19 @@ _PG_init(void)
201201
NULL
202202
);
203203

204+
DefineCustomBoolVariable(
205+
"aqo.learn_statement_timeout",
206+
"Learn on a plan interrupted by statement timeout.",
207+
"ML data stored in a backend cache, so it works only locally.",
208+
&aqo_learn_statement_timeout,
209+
false,
210+
PGC_USERSET,
211+
0,
212+
NULL,
213+
lc_assign_hook,
214+
NULL
215+
);
216+
204217
prev_planner_hook = planner_hook;
205218
planner_hook = aqo_planner;
206219
prev_ExecutorStart_hook = ExecutorStart_hook;

learn_cache.c

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
*/
1414

1515
#include "postgres.h"
16+
#include "miscadmin.h"
1617

1718
#include "aqo.h"
1819
#include "learn_cache.h"
@@ -39,6 +40,8 @@ typedef struct
3940
static HTAB *fss_htab = NULL;
4041
MemoryContext LearnCacheMemoryContext = NULL;
4142

43+
bool aqo_learn_statement_timeout = false;
44+
4245
void
4346
lc_init(void)
4447
{
@@ -66,7 +69,7 @@ lc_update_fss(uint64 fs, int fss, int nrows, int ncols,
6669
int i;
6770
MemoryContext memctx = MemoryContextSwitchTo(LearnCacheMemoryContext);
6871

69-
Assert(fss_htab);
72+
Assert(fss_htab && aqo_learn_statement_timeout);
7073

7174
entry = (htab_entry *) hash_search(fss_htab, &key, HASH_ENTER, &found);
7275
if (found)
@@ -99,6 +102,9 @@ lc_has_fss(uint64 fs, int fss)
99102
htab_key key = {fs, fss};
100103
bool found;
101104

105+
if (!aqo_learn_statement_timeout)
106+
return false;
107+
102108
Assert(fss_htab);
103109

104110
(void) hash_search(fss_htab, &key, HASH_FIND, &found);
@@ -118,7 +124,7 @@ lc_load_fss(uint64 fs, int fss, int ncols, double **matrix,
118124
bool found;
119125
int i;
120126

121-
Assert(fss_htab);
127+
Assert(fss_htab && aqo_learn_statement_timeout);
122128

123129
entry = (htab_entry *) hash_search(fss_htab, &key, HASH_FIND, &found);
124130
if (!found)
@@ -150,6 +156,9 @@ lc_remove_fss(uint64 fs, int fss)
150156
bool found;
151157
int i;
152158

159+
if (!aqo_learn_statement_timeout)
160+
return;
161+
153162
Assert(fss_htab);
154163

155164
entry = (htab_entry *) hash_search(fss_htab, &key, HASH_FIND, &found);
@@ -161,3 +170,31 @@ lc_remove_fss(uint64 fs, int fss)
161170
pfree(entry->targets);
162171
hash_search(fss_htab, &key, HASH_REMOVE, NULL);
163172
}
173+
174+
/*
175+
* Main purpose of this hook is to cleanup a backend cache in some way to prevent
176+
* memory leaks - in large queries we could have many unused fss nodes.
177+
*/
178+
void
179+
lc_assign_hook(bool newval, void *extra)
180+
{
181+
HASH_SEQ_STATUS status;
182+
htab_entry *entry;
183+
184+
if (!fss_htab || !IsUnderPostmaster)
185+
return;
186+
187+
/* Remove all entries, reset memory context. */
188+
189+
elog(DEBUG5, "[AQO] Cleanup local cache of ML data.");
190+
191+
/* Remove all frozen plans from a plancache. */
192+
hash_seq_init(&status, fss_htab);
193+
while ((entry = (htab_entry *) hash_seq_search(&status)) != NULL)
194+
{
195+
if (!hash_search(fss_htab, (void *) &entry->key, HASH_REMOVE, NULL))
196+
elog(ERROR, "[AQO] The local ML cache is corrupted.");
197+
}
198+
199+
MemoryContextReset(LearnCacheMemoryContext);
200+
}

learn_cache.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
#include "nodes/pg_list.h"
55

6+
extern bool aqo_learn_statement_timeout;
7+
68
extern void lc_init(void);
79
extern bool lc_update_fss(uint64 fhash, int fsshash, int nrows, int ncols,
810
double **matrix, double *targets, List *relids);
@@ -11,5 +13,6 @@ extern bool lc_load_fss(uint64 fhash, int fsshash, int ncols,
1113
double **matrix, double *targets, int *nrows,
1214
List **relids);
1315
extern void lc_remove_fss(uint64 fhash, int fss_hash);
16+
extern void lc_assign_hook(bool newval, void *extra);
1417

1518
#endif /* LEARN_CACHE_H */

postprocessing.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,7 @@ set_timeout_if_need(QueryDesc *queryDesc)
684684
{
685685
TimestampTz fin_time;
686686

687-
if (!get_timeout_active(STATEMENT_TIMEOUT))
687+
if (!get_timeout_active(STATEMENT_TIMEOUT) || !aqo_learn_statement_timeout)
688688
return false;
689689

690690
if (!ExtractFromQueryEnv(queryDesc))
@@ -696,7 +696,7 @@ set_timeout_if_need(QueryDesc *queryDesc)
696696

697697
/*
698698
* Statement timeout exists. AQO should create user timeout right before the
699-
* statement timeout.
699+
* timeout.
700700
*/
701701

702702
if (timeoutCtl.id < USER_TIMEOUT)

storage.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,10 +369,12 @@ load_fss_ext(uint64 fs, int fss,
369369
int ncols, double **matrix, double *targets, int *rows,
370370
List **relids, bool isSafe)
371371
{
372-
if (isSafe && !lc_has_fss(fs, fss))
372+
if (isSafe && (!aqo_learn_statement_timeout || !lc_has_fss(fs, fss)))
373373
return load_fss(fs, fss, ncols, matrix, targets, rows, relids);
374374
else
375375
{
376+
Assert(aqo_learn_statement_timeout);
377+
376378
if (matrix == NULL && targets == NULL && rows == NULL)
377379
return true;
378380

0 commit comments

Comments
 (0)