Change GEQO optimizer to release memory after each gene
authorTom Lane
Mon, 17 May 1999 00:25:34 +0000 (00:25 +0000)
committerTom Lane
Mon, 17 May 1999 00:25:34 +0000 (00:25 +0000)
is evaluated.  This bounds memory usage to something reasonable even
when many tables are being joined.

src/backend/optimizer/geqo/geqo_eval.c
src/backend/optimizer/geqo/geqo_main.c
src/backend/optimizer/geqo/geqo_params.c
src/include/optimizer/geqo.h

index 093d09ba975dd20ef783cb2572bf0a460b81bf72..31a77f46e4a3a6de68f7a77e88eb8523547bf547 100644 (file)
@@ -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"
 #include "optimizer/geqo_gene.h"
 #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
  *
 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;
 }
index 76beb7c2495471457cce13da3f5aada9a9c72ced..2cedda675bdb8406e36ce79156d7d7d250907629 100644 (file)
@@ -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);
 
index 1c664c1b3b1f4abd31ec1c32a128de6925183985..130b6355ac6705de6fa9869457a8b13c2fc5ea06 100644 (file)
@@ -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 $
 *
 *-------------------------------------------------------------------------
 */
 
 #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;
index 9a4c61d4a0556e717df1e26be8e0dbe85d4418c6..aba1d86096b4a6ae8415e758cec702aac8cbfcf8 100644 (file)
@@ -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 $
  *
  *-------------------------------------------------------------------------
  */
 #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 */