OverrideSearchPathMatchesCurrent performance improvement - Mailing list pgsql-hackers

From Tom Lane
Subject OverrideSearchPathMatchesCurrent performance improvement
Date
Msg-id 15447.1417120906@sss.pgh.pa.us
Whole thread Raw
List pgsql-hackers
The other thing that emerged from
http://www.postgresql.org/message-id/flat/CAOR=d=3j1U_q-zf8+jUx1hkx8ps+N8pm=EUTqyFdJ5ov=+fawg@mail.gmail.com
is that for workloads like this, OverrideSearchPathMatchesCurrent is
a bottleneck: it's part of the code path needed to re-use a cached plan,
and this example is doing a lot of that.  The original implementation
of that function followed the KISS principle, since I thought it probably
wouldn't be a bottleneck.  Now that that's proven wrong, I offer the
attached reimplementation, which saves about 9% of overall runtime on
Scott's example by avoiding palloc/pfree traffic.  It knows a lot more
about the relation of override search paths to active search paths than
it did before; but the adjacent functions know these things too, so it
doesn't seem like much of a loss from a maintainability standpoint.

            regards, tom lane

diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 911f015..7a06332 100644
*** a/src/backend/catalog/namespace.c
--- b/src/backend/catalog/namespace.c
*************** CopyOverrideSearchPath(OverrideSearchPat
*** 3145,3164 ****
  bool
  OverrideSearchPathMatchesCurrent(OverrideSearchPath *path)
  {
!     /* Easiest way to do this is GetOverrideSearchPath() and compare */
!     bool        result;
!     OverrideSearchPath *cur;

!     cur = GetOverrideSearchPath(CurrentMemoryContext);
!     if (path->addCatalog == cur->addCatalog &&
!         path->addTemp == cur->addTemp &&
!         equal(path->schemas, cur->schemas))
!         result = true;
!     else
!         result = false;
!     list_free(cur->schemas);
!     pfree(cur);
!     return result;
  }

  /*
--- 3145,3188 ----
  bool
  OverrideSearchPathMatchesCurrent(OverrideSearchPath *path)
  {
!     ListCell   *lc,
!                *lcp;

!     recomputeNamespacePath();
!
!     /* We scan down the activeSearchPath to see if it matches the input. */
!     lc = list_head(activeSearchPath);
!
!     /* If path->addTemp, first item should be my temp namespace. */
!     if (path->addTemp)
!     {
!         if (lc && lfirst_oid(lc) == myTempNamespace)
!             lc = lnext(lc);
!         else
!             return false;
!     }
!     /* If path->addCatalog, next item should be pg_catalog. */
!     if (path->addCatalog)
!     {
!         if (lc && lfirst_oid(lc) == PG_CATALOG_NAMESPACE)
!             lc = lnext(lc);
!         else
!             return false;
!     }
!     /* We should now be looking at the activeCreationNamespace. */
!     if (activeCreationNamespace != (lc ? lfirst_oid(lc) : InvalidOid))
!         return false;
!     /* The remainder of activeSearchPath should match path->schemas. */
!     foreach(lcp, path->schemas)
!     {
!         if (lc && lfirst_oid(lc) == lfirst_oid(lcp))
!             lc = lnext(lc);
!         else
!             return false;
!     }
!     if (lc)
!         return false;
!     return true;
  }

  /*

pgsql-hackers by date:

Previous
From: Michael Paquier
Date:
Subject: Re: [REVIEW] Re: Compression of full-page-writes
Next
From: Josh Berkus
Date:
Subject: Re: no test programs in contrib