]> granicus.if.org Git - postgresql/commitdiff
Replace linear searches with binary searches in pg_dump's code to
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 23 Sep 2007 23:39:36 +0000 (23:39 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 23 Sep 2007 23:39:36 +0000 (23:39 +0000)
lookup objects by OID.  Per gripe from nikitathespider.

src/bin/pg_dump/common.c

index 53d15ac970d047dde76567a6519dee81153d38be..639f2b92f9d8a14eae8c79c20242232c55308a59 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/bin/pg_dump/common.c,v 1.97 2007/08/21 01:11:20 tgl Exp $
+ *       $PostgreSQL: pgsql/src/bin/pg_dump/common.c,v 1.98 2007/09/23 23:39:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -41,7 +41,11 @@ static int   numCatalogIds = 0;
 
 /*
  * These variables are static to avoid the notational cruft of having to pass
- * them into findTableByOid() and friends.
+ * them into findTableByOid() and friends.  For each of these arrays, we
+ * build a sorted-by-OID index array immediately after it's built, and then
+ * we use binary search in findTableByOid() and friends.  (qsort'ing the base
+ * arrays themselves would be simpler, but it doesn't work because pg_dump.c
+ * may have already established pointers between items.)
  */
 static TableInfo *tblinfo;
 static TypeInfo *typinfo;
@@ -51,12 +55,18 @@ static int  numTables;
 static int     numTypes;
 static int     numFuncs;
 static int     numOperators;
+static DumpableObject **tblinfoindex;
+static DumpableObject **typinfoindex;
+static DumpableObject **funinfoindex;
+static DumpableObject **oprinfoindex;
 
 
 static void flagInhTables(TableInfo *tbinfo, int numTables,
                          InhInfo *inhinfo, int numInherits);
 static void flagInhAttrs(TableInfo *tbinfo, int numTables,
                         InhInfo *inhinfo, int numInherits);
+static DumpableObject **buildIndexArray(void *objArray, int numObjs,
+                                                                               Size objSize);
 static int     DOCatalogIdCompare(const void *p1, const void *p2);
 static void findParentsByOid(TableInfo *self,
                                 InhInfo *inhinfo, int numInherits);
@@ -104,11 +114,13 @@ getSchemaData(int *numTablesPtr)
        if (g_verbose)
                write_msg(NULL, "reading user-defined functions\n");
        funinfo = getFuncs(&numFuncs);
+       funinfoindex = buildIndexArray(funinfo, numFuncs, sizeof(FuncInfo));
 
        /* this must be after getFuncs */
        if (g_verbose)
                write_msg(NULL, "reading user-defined types\n");
        typinfo = getTypes(&numTypes);
+       typinfoindex = buildIndexArray(typinfo, numTypes, sizeof(TypeInfo));
 
        /* this must be after getFuncs, too */
        if (g_verbose)
@@ -122,6 +134,7 @@ getSchemaData(int *numTablesPtr)
        if (g_verbose)
                write_msg(NULL, "reading user-defined operators\n");
        oprinfo = getOperators(&numOperators);
+       oprinfoindex = buildIndexArray(oprinfo, numOperators, sizeof(OprInfo));
 
        if (g_verbose)
                write_msg(NULL, "reading user-defined operator classes\n");
@@ -154,6 +167,7 @@ getSchemaData(int *numTablesPtr)
        if (g_verbose)
                write_msg(NULL, "reading user-defined tables\n");
        tblinfo = getTables(&numTables);
+       tblinfoindex = buildIndexArray(tblinfo, numTables, sizeof(TableInfo));
 
        if (g_verbose)
                write_msg(NULL, "reading table inheritance information\n");
@@ -540,6 +554,70 @@ findObjectByCatalogId(CatalogId catalogId)
        return NULL;
 }
 
+/*
+ * Find a DumpableObject by OID, in a pre-sorted array of one type of object
+ *
+ * Returns NULL for unknown OID
+ */
+static DumpableObject *
+findObjectByOid(Oid oid, DumpableObject **indexArray, int numObjs)
+{
+       DumpableObject **low;
+       DumpableObject **high;
+
+       /*
+        * This is the same as findObjectByCatalogId except we assume we need
+        * not look at table OID because the objects are all the same type.
+        *
+        * 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 (numObjs <= 0)
+               return NULL;
+       low = indexArray;
+       high = indexArray + (numObjs - 1);
+       while (low <= high)
+       {
+               DumpableObject **middle;
+               int                     difference;
+
+               middle = low + (high - low) / 2;
+               difference = oidcmp((*middle)->catId.oid, oid);
+               if (difference == 0)
+                       return *middle;
+               else if (difference < 0)
+                       low = middle + 1;
+               else
+                       high = middle - 1;
+       }
+       return NULL;
+}
+
+/*
+ * Build an index array of DumpableObject pointers, sorted by OID
+ */
+static DumpableObject **
+buildIndexArray(void *objArray, int numObjs, Size objSize)
+{
+       DumpableObject **ptrs;
+       int             i;
+
+       ptrs = (DumpableObject **) malloc(numObjs * sizeof(DumpableObject *));
+       for (i = 0; i < numObjs; i++)
+               ptrs[i] = (DumpableObject *) ((char *) objArray + i * objSize);
+
+       /* We can use DOCatalogIdCompare to sort since its first key is OID */
+       if (numObjs > 1)
+               qsort((void *) ptrs, numObjs, sizeof(DumpableObject *),
+                         DOCatalogIdCompare);
+
+       return ptrs;
+}
+
+/*
+ * qsort comparator for pointers to DumpableObjects
+ */
 static int
 DOCatalogIdCompare(const void *p1, const void *p2)
 {
@@ -630,80 +708,44 @@ removeObjectDependency(DumpableObject *dobj, DumpId refId)
  * findTableByOid
  *       finds the entry (in tblinfo) of the table with the given oid
  *       returns NULL if not found
- *
- * NOTE:  should hash this, but just do linear search for now
  */
 TableInfo *
 findTableByOid(Oid oid)
 {
-       int                     i;
-
-       for (i = 0; i < numTables; i++)
-       {
-               if (tblinfo[i].dobj.catId.oid == oid)
-                       return &tblinfo[i];
-       }
-       return NULL;
+       return (TableInfo *) findObjectByOid(oid, tblinfoindex, numTables);
 }
 
 /*
  * findTypeByOid
  *       finds the entry (in typinfo) of the type with the given oid
  *       returns NULL if not found
- *
- * NOTE:  should hash this, but just do linear search for now
  */
 TypeInfo *
 findTypeByOid(Oid oid)
 {
-       int                     i;
-
-       for (i = 0; i < numTypes; i++)
-       {
-               if (typinfo[i].dobj.catId.oid == oid)
-                       return &typinfo[i];
-       }
-       return NULL;
+       return (TypeInfo *) findObjectByOid(oid, typinfoindex, numTypes);
 }
 
 /*
  * findFuncByOid
  *       finds the entry (in funinfo) of the function with the given oid
  *       returns NULL if not found
- *
- * NOTE:  should hash this, but just do linear search for now
  */
 FuncInfo *
 findFuncByOid(Oid oid)
 {
-       int                     i;
-
-       for (i = 0; i < numFuncs; i++)
-       {
-               if (funinfo[i].dobj.catId.oid == oid)
-                       return &funinfo[i];
-       }
-       return NULL;
+       return (FuncInfo *) findObjectByOid(oid, funinfoindex, numFuncs);
 }
 
 /*
  * findOprByOid
  *       finds the entry (in oprinfo) of the operator with the given oid
  *       returns NULL if not found
- *
- * NOTE:  should hash this, but just do linear search for now
  */
 OprInfo *
 findOprByOid(Oid oid)
 {
-       int                     i;
-
-       for (i = 0; i < numOperators; i++)
-       {
-               if (oprinfo[i].dobj.catId.oid == oid)
-                       return &oprinfo[i];
-       }
-       return NULL;
+       return (OprInfo *) findObjectByOid(oid, oprinfoindex, numOperators);
 }