summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane1999-05-17 00:25:34 +0000
committerTom Lane1999-05-17 00:25:34 +0000
commit1332c1e14404407c9a106bf7096e8f58b16dc566 (patch)
tree523343f9485b4fc7cae696786787bfaccaf49b83
parentc686be8d5687f5e31df0a97ee52ccfe5842071b5 (diff)
Change GEQO optimizer to release memory after each gene
is evaluated. This bounds memory usage to something reasonable even when many tables are being joined.
-rw-r--r--src/backend/optimizer/geqo/geqo_eval.c60
-rw-r--r--src/backend/optimizer/geqo/geqo_main.c34
-rw-r--r--src/backend/optimizer/geqo/geqo_params.c14
-rw-r--r--src/include/optimizer/geqo.h25
4 files changed, 84 insertions, 49 deletions
diff --git a/src/backend/optimizer/geqo/geqo_eval.c b/src/backend/optimizer/geqo/geqo_eval.c
index 093d09ba97..31a77f46e4 100644
--- a/src/backend/optimizer/geqo/geqo_eval.c
+++ b/src/backend/optimizer/geqo/geqo_eval.c
@@ -5,7 +5,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: geqo_eval.c,v 1.36 1999/05/16 19:45:00 tgl Exp $
+ * $Id: geqo_eval.c,v 1.37 1999/05/17 00:25:34 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -36,6 +36,7 @@
#include "utils/palloc.h"
#include "utils/elog.h"
+#include "utils/portal.h"
#include "optimizer/internal.h"
#include "optimizer/paths.h"
@@ -49,6 +50,38 @@
#include "optimizer/geqo.h"
/*
+ * Variables set by geqo_eval_startup for use within a single GEQO run
+ */
+static MemoryContext geqo_eval_context;
+
+/*
+ * geqo_eval_startup:
+ * Must be called during geqo_main startup (before geqo_eval may be called)
+ *
+ * The main thing we need to do here is prepare a private memory context for
+ * allocation of temp storage used while constructing a path in geqo_eval().
+ * Since geqo_eval() will be called many times, we can't afford to let all
+ * that memory go unreclaimed until end of statement. We use a special
+ * named portal to hold the context, so that it will be freed even if
+ * we abort via elog(ERROR). The working data is allocated in the portal's
+ * heap memory context.
+ */
+void
+geqo_eval_startup(void)
+{
+#define GEQO_PORTAL_NAME "<geqo workspace>"
+ Portal geqo_portal = GetPortalByName(GEQO_PORTAL_NAME);
+
+ if (!PortalIsValid(geqo_portal)) {
+ /* First time through (within current transaction, that is) */
+ geqo_portal = CreatePortal(GEQO_PORTAL_NAME);
+ Assert(PortalIsValid(geqo_portal));
+ }
+
+ geqo_eval_context = (MemoryContext) PortalGetHeapMemory(geqo_portal);
+}
+
+/*
* geqo_eval
*
* Returns cost of a query tree as an individual of the population.
@@ -56,23 +89,30 @@
Cost
geqo_eval(Query *root, Gene *tour, int num_gene)
{
- RelOptInfo *joinrel;
- Cost fitness;
- List *temp;
+ MemoryContext oldcxt;
+ RelOptInfo *joinrel;
+ Cost fitness;
+ List *savelist;
+
+ /* preserve root->join_rel_list, which gimme_tree changes */
+ savelist = root->join_rel_list;
- /* remember root->join_rel_list ... */
- /* because root->join_rel_list will be changed during the following */
- temp = listCopy(root->join_rel_list);
+ /* create a temporary allocation context for the path construction work */
+ oldcxt = MemoryContextSwitchTo(geqo_eval_context);
+ StartPortalAllocMode(DefaultAllocMode, 0);
- /* joinrel is readily processed query tree -- left-sided ! */
+ /* construct the best path for the given combination of relations */
joinrel = gimme_tree(root, tour, 0, num_gene, NULL);
/* compute fitness */
fitness = (Cost) joinrel->cheapestpath->path_cost;
- root->join_rel_list = temp;
+ /* restore join_rel_list */
+ root->join_rel_list = savelist;
- pfree(joinrel);
+ /* release all the memory acquired within gimme_tree */
+ EndPortalAllocMode();
+ MemoryContextSwitchTo(oldcxt);
return fitness;
}
diff --git a/src/backend/optimizer/geqo/geqo_main.c b/src/backend/optimizer/geqo/geqo_main.c
index 76beb7c249..2cedda675b 100644
--- a/src/backend/optimizer/geqo/geqo_main.c
+++ b/src/backend/optimizer/geqo/geqo_main.c
@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: geqo_main.c,v 1.14 1999/02/18 04:55:54 momjian Exp $
+ * $Id: geqo_main.c,v 1.15 1999/05/17 00:25:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -70,44 +70,31 @@ geqo(Query *root)
Chromosome *momma;
Chromosome *daddy;
Chromosome *kid;
-
+ int number_of_rels;
+ Pool *pool;
+ int pool_size,
+ number_generations,
+ status_interval;
+ Gene *best_tour;
+ RelOptInfo *best_rel;
#if defined(ERX)
Edge *edge_table; /* list of edges */
int edge_failures = 0;
float difference;
-
#endif
-
#if defined(CX) || defined(PX) || defined(OX1) || defined(OX2)
City *city_table; /* list of cities */
-
#endif
-
#if defined(CX)
int cycle_diffs = 0;
int mutations = 0;
-
#endif
-
- int number_of_rels;
-
- Pool *pool;
- int pool_size,
- number_generations,
- status_interval;
-
- Gene *best_tour;
- RelOptInfo *best_rel;
-
-/* Plan *best_plan; */
-
-
/* set tour size */
number_of_rels = length(root->base_rel_list);
/* set GA parameters */
- geqo_params(number_of_rels);/* out of "$PGDATA/pg_geqo" file */
+ geqo_params(number_of_rels); /* read "$PGDATA/pg_geqo" file */
pool_size = PoolSize;
number_generations = Generations;
status_interval = 10;
@@ -115,6 +102,9 @@ geqo(Query *root)
/* seed random number generator */
srandom(RandomSeed);
+/* initialize plan evaluator */
+ geqo_eval_startup();
+
/* allocate genetic pool memory */
pool = alloc_pool(pool_size, number_of_rels);
diff --git a/src/backend/optimizer/geqo/geqo_params.c b/src/backend/optimizer/geqo/geqo_params.c
index 1c664c1b3b..130b6355ac 100644
--- a/src/backend/optimizer/geqo/geqo_params.c
+++ b/src/backend/optimizer/geqo/geqo_params.c
@@ -5,7 +5,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
-* $Id: geqo_params.c,v 1.14 1999/02/15 03:22:01 momjian Exp $
+* $Id: geqo_params.c,v 1.15 1999/05/17 00:25:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -45,6 +45,16 @@
#include "storage/fd.h"
+/*
+ * Parameter values read from the config file (or defaulted) are stored here
+ * by geqo_params().
+ */
+int PoolSize;
+int Generations;
+long RandomSeed;
+double SelectionBias;
+
+
#define POOL_TAG "Pool_Size"
#define TRIAL_TAG "Generations"
#define RAND_TAG "Random_Seed"
@@ -77,7 +87,7 @@ geqo_params(int string_length)
char *conf_file;
-/* these static variables are used to signal that a value has been set */
+ /* these flag variables signal that a value has been set from the file */
int pool_size = 0;
int number_trials = 0;
int random_seed = 0;
diff --git a/src/include/optimizer/geqo.h b/src/include/optimizer/geqo.h
index 9a4c61d4a0..aba1d86096 100644
--- a/src/include/optimizer/geqo.h
+++ b/src/include/optimizer/geqo.h
@@ -5,7 +5,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: geqo.h,v 1.13 1999/02/18 04:55:54 momjian Exp $
+ * $Id: geqo.h,v 1.14 1999/05/17 00:25:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -56,27 +56,22 @@
#define SELECTION_BIAS 2.0 /* selective pressure within population */
/* should be 1.5 <= SELECTION_BIAS <= 2.0 */
-int PoolSize;
-int Generations;
+/* parameter values set in geqo_params.c */
+extern int PoolSize;
+extern int Generations;
+extern long RandomSeed;
+extern double SelectionBias;
-long RandomSeed; /* defaults to (long) time(NULL) in
- * geqo_params.c */
-double SelectionBias;
-
-/* logarithmic base for rel->size decrease in case of long
- queries that cause an integer overflow; used in geqo_eval.c */
-
-#define GEQO_LOG_BASE 1.5 /* should be 1.0 < GEQO_LOG_BASE <= 2.0 */
- /* ^^^ */
-
-/* geqo prototypes */
+/* routines in geqo_main.c */
extern RelOptInfo *geqo(Query *root);
+/* routines in geqo_params.c */
extern void geqo_params(int string_length);
+/* routines in geqo_eval.c */
+extern void geqo_eval_startup(void);
extern Cost geqo_eval(Query *root, Gene *tour, int num_gene);
extern RelOptInfo *gimme_tree(Query *root, Gene *tour, int rel_count,
int num_gene, RelOptInfo *old_rel);
-
#endif /* GEQO_H */