]> granicus.if.org Git - postgresql/commitdiff
Speed up findObjectByCatalogId() to get rid of the other salient
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 7 Dec 2003 03:14:01 +0000 (03:14 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 7 Dec 2003 03:14:01 +0000 (03:14 +0000)
bottleneck in the new pg_dump code.

src/bin/pg_dump/common.c

index 81d9cc284c9812c26619724391cd09582c30b95d..45bc90fcccb5784cf7ad26e8825df2a20a16255f 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/bin/pg_dump/common.c,v 1.78 2003/12/06 03:00:11 tgl Exp $
+ *       $PostgreSQL: pgsql/src/bin/pg_dump/common.c,v 1.79 2003/12/07 03:14:01 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -37,6 +37,13 @@ static DumpableObject **dumpIdMap = NULL;
 static int     allocedDumpIds = 0;
 static DumpId lastDumpId = 0;
 
+/*
+ * Variables for mapping CatalogId to DumpableObject
+ */
+static bool catalogIdMapValid = false;
+static DumpableObject **catalogIdMap = NULL;
+static int     numCatalogIds = 0;
+
 /*
  * These variables are static to avoid the notational cruft of having to pass
  * them into findTableByOid() and friends.
@@ -51,12 +58,13 @@ static int          numFuncs;
 static int             numOperators;
 
 
-static void findParentsByOid(TableInfo *self,
-                                                        InhInfo *inhinfo, int numInherits);
 static void flagInhTables(TableInfo *tbinfo, int numTables,
                          InhInfo *inhinfo, int numInherits);
 static void flagInhAttrs(TableInfo *tbinfo, int numTables,
                         InhInfo *inhinfo, int numInherits);
+static int     DOCatalogIdCompare(const void *p1, const void *p2);
+static void findParentsByOid(TableInfo *self,
+                                                        InhInfo *inhinfo, int numInherits);
 static int     strInArray(const char *pattern, char **arr, int arr_size);
 
 
@@ -413,6 +421,9 @@ AssignDumpId(DumpableObject *dobj)
                allocedDumpIds = newAlloc;
        }
        dumpIdMap[dobj->dumpId] = dobj;
+
+       /* mark catalogIdMap invalid, but don't rebuild it yet */
+       catalogIdMapValid = false;
 }
 
 /*
@@ -454,25 +465,74 @@ findObjectByDumpId(DumpId dumpId)
  *
  * Returns NULL for unknown ID
  *
- * NOTE:  should hash this, but just do linear search for now
+ * We use binary search in a sorted list that is built on first call.
+ * If AssignDumpId() and findObjectByCatalogId() calls were intermixed,
+ * the code would work, but possibly be very slow.  In the current usage
+ * pattern that does not happen, indeed we only need to build the list once.
  */
 DumpableObject *
 findObjectByCatalogId(CatalogId catalogId)
 {
-       DumpId          i;
+       DumpableObject **low;
+       DumpableObject **high;
 
-       for (i = 1; i < allocedDumpIds; i++)
+       if (!catalogIdMapValid)
        {
-               DumpableObject *dobj = dumpIdMap[i];
+               if (catalogIdMap)
+                       free(catalogIdMap);
+               getDumpableObjects(&catalogIdMap, &numCatalogIds);
+               if (numCatalogIds > 1)
+                       qsort((void *) catalogIdMap, numCatalogIds,
+                                 sizeof(DumpableObject *), DOCatalogIdCompare);
+               catalogIdMapValid = true;
+       }
 
-               if (dobj &&
-                       dobj->catId.tableoid == catalogId.tableoid &&
-                       dobj->catId.oid == catalogId.oid)
-                       return dobj;
+       /*
+        * We could use bsearch() here, but the notational cruft of calling
+        * bsearch is nearly as bad as doing it ourselves; and the generalized
+        * bsearch function is noticeably slower as well.
+        */
+       if (numCatalogIds <= 0)
+               return NULL;
+       low = catalogIdMap;
+       high = catalogIdMap + (numCatalogIds - 1);
+       while (low <= high)
+       {
+               DumpableObject **middle;
+               int                     difference;
+
+               middle = low + (high - low) / 2;
+               /* comparison must match DOCatalogIdCompare, below */
+               difference = oidcmp((*middle)->catId.oid, catalogId.oid);
+               if (difference == 0)
+                       difference = oidcmp((*middle)->catId.tableoid, catalogId.tableoid);
+               if (difference == 0)
+                       return *middle;
+               else if (difference < 0)
+                       low = middle + 1;
+               else
+                       high = middle - 1;
        }
        return NULL;
 }
 
+static int
+DOCatalogIdCompare(const void *p1, const void *p2)
+{
+       DumpableObject *obj1 = *(DumpableObject **) p1;
+       DumpableObject *obj2 = *(DumpableObject **) p2;
+       int                     cmpval;
+
+       /*
+        * Compare OID first since it's usually unique, whereas there will
+        * only be a few distinct values of tableoid.
+        */
+       cmpval = oidcmp(obj1->catId.oid, obj2->catId.oid);
+       if (cmpval == 0)
+               cmpval = oidcmp(obj1->catId.tableoid, obj2->catId.tableoid);
+       return cmpval;
+}
+
 /*
  * Build an array of pointers to all known dumpable objects
  *