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
  *