[postgis-tickets] r17547 - PROJ: Remove the extra MemoryContext for PG9.6+

Raul raul at rmr.ninja
Wed Jun 19 08:23:33 PDT 2019


Author: algunenano
Date: 2019-06-19 08:23:33 -0700 (Wed, 19 Jun 2019)
New Revision: 17547

Modified:
   trunk/libpgcommon/lwgeom_cache.c
   trunk/libpgcommon/lwgeom_cache.h
   trunk/libpgcommon/lwgeom_transform.c
Log:
PROJ: Remove the extra MemoryContext for PG9.6+

In PG9.6+ we can allocate callbacks in the parent node
and associate them directly without creating new contextes

References #4372


Modified: trunk/libpgcommon/lwgeom_cache.c
===================================================================
--- trunk/libpgcommon/lwgeom_cache.c	2019-06-19 15:21:29 UTC (rev 17546)
+++ trunk/libpgcommon/lwgeom_cache.c	2019-06-19 15:23:33 UTC (rev 17547)
@@ -93,19 +93,11 @@
 
 		if (cache)
 		{
-			int i;
-
 			POSTGIS_DEBUGF(3,
 				       "Allocating PROJCache for portal with transform() MemoryContext %p",
 				       FIContext(fcinfo));
 			/* Put in any required defaults */
-			for (i = 0; i < PROJ_CACHE_ITEMS; i++)
-			{
-				cache->PROJSRSCache[i].srid_from = SRID_UNKNOWN;
-				cache->PROJSRSCache[i].srid_to = SRID_UNKNOWN;
-				cache->PROJSRSCache[i].projection = NULL;
-				cache->PROJSRSCache[i].projection_mcxt = NULL;
-			}
+			memset(cache->PROJSRSCache, 0, sizeof(PROJSRSCacheItem) * PROJ_CACHE_ITEMS);
 			cache->type = PROJ_CACHE_ENTRY;
 			cache->PROJSRSCacheCount = 0;
 			cache->PROJSRSCacheContext = FIContext(fcinfo);

Modified: trunk/libpgcommon/lwgeom_cache.h
===================================================================
--- trunk/libpgcommon/lwgeom_cache.h	2019-06-19 15:21:29 UTC (rev 17546)
+++ trunk/libpgcommon/lwgeom_cache.h	2019-06-19 15:23:33 UTC (rev 17547)
@@ -68,7 +68,9 @@
 	int32_t srid_from;
 	int32_t srid_to;
 	LWPROJ *projection;
+#if POSTGIS_PGSQL_VERSION < 96
 	MemoryContext projection_mcxt;
+#endif
 }
 PROJSRSCacheItem;
 

Modified: trunk/libpgcommon/lwgeom_transform.c
===================================================================
--- trunk/libpgcommon/lwgeom_transform.c	2019-06-19 15:21:29 UTC (rev 17546)
+++ trunk/libpgcommon/lwgeom_transform.c	2019-06-19 15:23:33 UTC (rev 17547)
@@ -48,18 +48,6 @@
  */
 #define PROJ_BACKEND_HASH_SIZE 256
 
-/**
- * Backend PROJ hash table
- *
- * This hash table stores a key/value pair of MemoryContext/PJ objects.
- * Whenever we create a PJ object using pj_init(), we create a separate
- * MemoryContext as a child context of the current executor context.
- * The MemoryContext/PJ object is stored in this hash table so
- * that when PROJSRSCacheDelete() is called during query cleanup, we can
- * lookup the PJ object based upon the MemoryContext parameter and hence
- * pj_free() it.
- */
-static HTAB *PJHash = NULL;
 
 /**
  * Utility structure to get many potential string representations
@@ -71,23 +59,6 @@
 	char* proj4text;
 } PjStrs;
 
-
-typedef struct struct_PJHashEntry
-{
-	MemoryContext ProjectionContext;
-	LWPROJ *projection;
-}
-PJHashEntry;
-
-
-/* PJ Hash API */
-uint32 mcxt_ptr_hash(const void *key, Size keysize);
-
-static HTAB *CreatePJHash(void);
-static void DeletePJHashEntry(MemoryContext mcxt);
-static LWPROJ *GetPJHashEntry(MemoryContext mcxt);
-static void AddPJHashEntry(MemoryContext mcxt, LWPROJ *projection);
-
 /* Internal Cache API */
 static LWPROJ *AddToPROJSRSCache(PROJPortalCache *PROJCache, int32_t srid_from, int32_t srid_to);
 static void DeleteFromPROJSRSCache(PROJPortalCache *PROJCache, int32_t srid_from, int32_t srid_to);
@@ -118,42 +89,61 @@
 }
 
 static void
-PROJSRSDestroyPJ(LWPROJ *pj)
+PROJSRSDestroyPJ(void *projection)
 {
+	LWPROJ *pj = (LWPROJ *)projection;
 #if POSTGIS_PROJ_VERSION < 60
 /* Ape the Proj 6+ API for versions < 6 */
 	if (pj->pj_from)
+	{
 		pj_free(pj->pj_from);
+		pj->pj_from = NULL;
+	}
 	if (pj->pj_to)
+	{
 		pj_free(pj->pj_to);
-	pfree(pj);
+		pj->pj_to = NULL;
+	}
 #else
-	proj_destroy(pj->pj);
-	pfree(pj);
+	if (pj->pj)
+	{
+		proj_destroy(pj->pj);
+		pj->pj = NULL;
+	}
 #endif
 }
 
-#if 0
-static const char *
-PJErrStr()
+#if POSTGIS_PGSQL_VERSION < 96
+/**
+ * Backend PROJ hash table
+ *
+ * This hash table stores a key/value pair of MemoryContext/PJ objects.
+ * Whenever we create a PJ object using pj_init(), we create a separate
+ * MemoryContext as a child context of the current executor context.
+ * The MemoryContext/PJ object is stored in this hash table so
+ * that when PROJSRSCacheDelete() is called during query cleanup, we can
+ * lookup the PJ object based upon the MemoryContext parameter and hence
+ * pj_free() it.
+ */
+static HTAB *PJHash = NULL;
+
+typedef struct struct_PJHashEntry
 {
-	const char *pj_errstr = pj_strerrno(*pj_get_errno_ref());
-	if (!pj_errstr)
-		return "";
-	return pj_errstr;
-}
-#endif
+	MemoryContext ProjectionContext;
+	LWPROJ *projection;
+} PJHashEntry;
 
+/* PJ Hash API */
+uint32 mcxt_ptr_hash(const void *key, Size keysize);
+
+static HTAB *CreatePJHash(void);
+static void DeletePJHashEntry(MemoryContext mcxt);
+static LWPROJ *GetPJHashEntry(MemoryContext mcxt);
+static void AddPJHashEntry(MemoryContext mcxt, LWPROJ *projection);
+
 static void
-#if POSTGIS_PGSQL_VERSION < 96
 PROJSRSCacheDelete(MemoryContext context)
 {
-#else
-PROJSRSCacheDelete(void *ptr)
-{
-	MemoryContext context = (MemoryContext)ptr;
-#endif
-
 	/* Lookup the PJ pointer in the global hash table so we can free it */
 	LWPROJ *projection = GetPJHashEntry(context);
 
@@ -168,8 +158,6 @@
 	DeletePJHashEntry(context);
 }
 
-#if POSTGIS_PGSQL_VERSION < 96
-
 static void
 PROJSRSCacheInit(MemoryContext context)
 {
@@ -237,7 +225,6 @@
 #endif
 };
 
-#endif /* POSTGIS_PGSQL_VERSION < 96 */
 
 /*
  * PROJ PJ Hash Table functions
@@ -327,6 +314,7 @@
 		he->projection = NULL;
 }
 
+#endif /* POSTGIS_PGSQL_VERSION < 96 */
 
 /*****************************************************************************
  * Per-cache management functions
@@ -600,7 +588,10 @@
 static LWPROJ *
 AddToPROJSRSCache(PROJPortalCache *PROJCache, int32_t srid_from, int32_t srid_to)
 {
-	MemoryContext PJMemoryContext, oldContext;
+#if POSTGIS_PGSQL_VERSION < 96
+	MemoryContext PJMemoryContext;
+#endif
+	MemoryContext oldContext;
 
 	PjStrs from_strs, to_strs;
 	char *pj_from_str, *pj_to_str;
@@ -710,38 +701,28 @@
 	                                      &PROJSRSCacheContextMethods,
 	                                      PROJCache->PROJSRSCacheContext,
 	                                      "PostGIS PROJ PJ Memory Context");
-#else
-	PJMemoryContext = AllocSetContextCreate(PROJCache->PROJSRSCacheContext,
-	                                        "PostGIS PROJ PJ Memory Context",
-	                                        ALLOCSET_SMALL_SIZES);
 
-	/* PgSQL comments suggest allocating callback in the context */
-	/* being managed, so that the callback object gets cleaned along with */
-	/* the context */
-	{
-		MemoryContextCallback *callback = MemoryContextAlloc(PJMemoryContext, sizeof(MemoryContextCallback));
-		callback->arg = (void*)PJMemoryContext;
-		callback->func = PROJSRSCacheDelete;
-		MemoryContextRegisterResetCallback(PJMemoryContext, callback);
-	}
-#endif
-
- 	/* Create the backend hash if it doesn't already exist */
+	/* We register a new memory context to use it to delete the projection on exit */
 	if (!PJHash)
 		PJHash = CreatePJHash();
 
-	/*
-	 * Add the MemoryContext to the backend hash so we can
-	 * clean up upon portal shutdown
-	 */
-	POSTGIS_DEBUGF(3, "adding projection object (%p) to hash table with MemoryContext key (%p)", projection, PJMemoryContext);
-
 	AddPJHashEntry(PJMemoryContext, projection);
 
+#else
+	/* We register a new callback to delete the projection on exit */
+	MemoryContextCallback *callback =
+	    MemoryContextAlloc(PROJCache->PROJSRSCacheContext, sizeof(MemoryContextCallback));
+	callback->func = PROJSRSDestroyPJ;
+	callback->arg = (void *)projection;
+	MemoryContextRegisterResetCallback(PROJCache->PROJSRSCacheContext, callback);
+#endif
+
 	PROJCache->PROJSRSCache[PROJCache->PROJSRSCacheCount].srid_from = srid_from;
 	PROJCache->PROJSRSCache[PROJCache->PROJSRSCacheCount].srid_to = srid_to;
 	PROJCache->PROJSRSCache[PROJCache->PROJSRSCacheCount].projection = projection;
+#if POSTGIS_PGSQL_VERSION < 96
 	PROJCache->PROJSRSCache[PROJCache->PROJSRSCacheCount].projection_mcxt = PJMemoryContext;
+#endif
 	PROJCache->PROJSRSCacheCount++;
 
 	MemoryContextSwitchTo(oldContext);
@@ -766,9 +747,16 @@
 			 * Zero out the entries and free the PROJ handle
 			 * by deleting the memory context
 			 */
+#if POSTGIS_PGSQL_VERSION < 96
+			/* Deleting the memory context will free the PROJ objects */
 			MemoryContextDelete(PROJCache->PROJSRSCache[i].projection_mcxt);
+			PROJCache->PROJSRSCache[i].projection_mcxt = NULL;
+#else
+			/* Call PROJSRSDestroyPJ to free the PROJ objects memory now instead of
+			 * waiting for the parent memory context to exit */
+			PROJSRSDestroyPJ(PROJCache->PROJSRSCache[i].projection);
+#endif
 			PROJCache->PROJSRSCache[i].projection = NULL;
-			PROJCache->PROJSRSCache[i].projection_mcxt = NULL;
 			PROJCache->PROJSRSCache[i].srid_from = SRID_UNKNOWN;
 			PROJCache->PROJSRSCache[i].srid_to = SRID_UNKNOWN;
 		}
@@ -796,7 +784,7 @@
 		*pj = AddToPROJSRSCache(proj_cache, srid_from, srid_to);
 	}
 
-	return LW_SUCCESS;
+	return pj != NULL;
 }
 
 static int



More information about the postgis-tickets mailing list