From 1332c1e14404407c9a106bf7096e8f58b16dc566 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 17 May 1999 00:25:34 +0000 Subject: [PATCH] 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. --- src/backend/optimizer/geqo/geqo_eval.c | 60 ++++++++++++++++++++++++++------ src/backend/optimizer/geqo/geqo_main.c | 34 +++++++----------- src/backend/optimizer/geqo/geqo_params.c | 14 ++++++-- src/include/optimizer/geqo.h | 25 ++++++------- 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 "" + 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 */ -- 2.11.0