[SCM] PostGIS branch master updated. 3.4.0rc1-884-g8489655ed

git at osgeo.org git at osgeo.org
Wed Jan 17 16:34:09 PST 2024


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "PostGIS".

The branch, master has been updated
       via  8489655ed88134a4478121041dbdb9ead12f6868 (commit)
      from  dd88d87cfc3b7b7b7f059171fb090ee4b2db8836 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 8489655ed88134a4478121041dbdb9ead12f6868
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Wed Jan 17 16:34:04 2024 -0800

    Improve performance of ST_GeneratePoints by... not using lwcollection_add_lwgeom()
    Apparently, for reasons not entirely clear, it is quite inefficient.
    In adding 50000 points to an empty multipoint with the function
    a solid 1000 ms of return time was from the collection filler, which
    is very large.

diff --git a/NEWS b/NEWS
index fa5958806..9679ccf22 100644
--- a/NEWS
+++ b/NEWS
@@ -49,6 +49,7 @@ To take advantage of all SFCGAL featurs, SFCGAL 1.5.0+ is needed.
   - GH-744, Don't create docbook.css for the HTML manual,
             use style.css instead (Chris Mayo)
   - Faster implementation of point-in-poly cached index (Paul Ramsey)
+  - Improve performance of ST_GeneratePoints (Paul Ramsey)
 
 
 PostGIS 3.4.0
diff --git a/liblwgeom/lwgeom_geos.c b/liblwgeom/lwgeom_geos.c
index 1c662d6e6..56eca41f3 100644
--- a/liblwgeom/lwgeom_geos.c
+++ b/liblwgeom/lwgeom_geos.c
@@ -29,6 +29,7 @@
 #include "liblwgeom_internal.h"
 #include "lwgeom_log.h"
 #include "lwrandom.h"
+#include "profile.h"
 
 #include <stdarg.h>
 #include <stdlib.h>
@@ -1400,7 +1401,7 @@ lwgeom_offsetcurve(const LWGEOM* geom, double size, int quadsegs, int joinStyle,
 }
 
 static GEOSGeometry*
-lwpoly_to_points_makepoly(double xmin, double ymin, double cell_size)
+lwpoly_to_points_make_cell(double xmin, double ymin, double cell_size)
 {
 	GEOSCoordSequence *cs = GEOSCoordSeq_create(5, 2);
 	GEOSCoordSeq_setXY(cs, 0, xmin, ymin);
@@ -1437,7 +1438,7 @@ lwpoly_to_points(const LWPOLY* lwpoly, uint32_t npoints, int32_t seed)
 	LWMPOINT* mpt;
 	int32_t srid = lwgeom_get_srid(lwgeom);
 	int done = 0;
-
+	LWPOINT **points_generated;
 
 	if (lwgeom_get_type(lwgeom) != POLYGONTYPE)
 	{
@@ -1502,12 +1503,14 @@ lwpoly_to_points(const LWPOLY* lwpoly, uint32_t npoints, int32_t seed)
 	}
 	gprep = GEOSPrepare(g);
 
+	/* START_PROFILING(); */
 
 	/* Now we fill in an array of cells, only using cells that actually
 	 * intersect the geometry of interest, and finally weshuffle that array,
 	 * so we can visit the cells in random order to avoid visual ugliness
 	 * caused by visiting them sequentially */
 	cells = lwalloc(sizeof(CellCorner) * sample_height * sample_width);
+
 	for (i = 0; i < sample_width; i++)
 	{
 		for (j = 0; j < sample_height; j++)
@@ -1515,11 +1518,11 @@ lwpoly_to_points(const LWPOLY* lwpoly, uint32_t npoints, int32_t seed)
 			int intersects = 0;
 			double xmin = bbox.xmin + i * sample_cell_size;
 			double ymin = bbox.ymin + j * sample_cell_size;
-			GEOSGeometry *gcell = lwpoly_to_points_makepoly(xmin, ymin, sample_cell_size);
+			GEOSGeometry *gcell = lwpoly_to_points_make_cell(xmin, ymin, sample_cell_size);
 			intersects = GEOSPreparedIntersects(gprep, gcell);
+			GEOSGeom_destroy(gcell);
 			if (intersects == 2)
 			{
-				GEOSGeom_destroy(gcell);
 				GEOSPreparedGeom_destroy(gprep);
 				GEOSGeom_destroy(g);
 				lwerror("%s: GEOS exception on GEOSPreparedIntersects: %s", __func__, lwgeom_geos_errmsg);
@@ -1531,10 +1534,11 @@ lwpoly_to_points(const LWPOLY* lwpoly, uint32_t npoints, int32_t seed)
 				cells[num_cells].y = ymin;
 				num_cells++;
 			}
-			GEOSGeom_destroy(gcell);
 		}
 	}
 
+	/* STOP_PROFILING(CellGeneration); */
+
 	/* Initiate random number generator.
 	 * Repeatable numbers are generated with seed values >= 1.
 	 * When seed is zero and has not previously been set, it is based on
@@ -1555,8 +1559,8 @@ lwpoly_to_points(const LWPOLY* lwpoly, uint32_t npoints, int32_t seed)
 		}
 	}
 
-	/* Get an empty multi-point ready to return */
-	mpt = lwmpoint_construct_empty(srid, 0, 0);
+	/* Get an empty array of points ready to return */
+	points_generated = lwalloc0(sizeof(LWGEOM*)*npoints);
 
 	/* Start testing points */
 	while (npoints_generated < npoints)
@@ -1583,7 +1587,6 @@ lwpoly_to_points(const LWPOLY* lwpoly, uint32_t npoints, int32_t seed)
 				GEOSGeom_destroy(gpt);
 			}
 #endif
-
 			if (contains == 2)
 			{
 				GEOSPreparedGeom_destroy(gprep);
@@ -1593,8 +1596,7 @@ lwpoly_to_points(const LWPOLY* lwpoly, uint32_t npoints, int32_t seed)
 			}
 			if (contains == 1)
 			{
-				npoints_generated++;
-				mpt = lwmpoint_add_lwpoint(mpt, lwpoint_make2d(srid, x, y));
+				points_generated[npoints_generated++] = lwpoint_make2d(srid, x, y);
 				if (npoints_generated == npoints)
 				{
 					done = 1;
@@ -1616,6 +1618,13 @@ lwpoly_to_points(const LWPOLY* lwpoly, uint32_t npoints, int32_t seed)
 	GEOSGeom_destroy(g);
 	lwfree(cells);
 
+	mpt = lwalloc0(sizeof(LWMPOINT));
+	mpt->type = MULTIPOINTTYPE;
+	mpt->geoms = points_generated;
+	mpt->ngeoms = npoints_generated;
+	mpt->maxgeoms = npoints;
+	mpt->srid = srid;
+
 	return mpt;
 }
 
diff --git a/liblwgeom/lwgeom_geos_clean.c b/liblwgeom/lwgeom_geos_clean.c
index 7eb1e907e..219a9f4fb 100644
--- a/liblwgeom/lwgeom_geos_clean.c
+++ b/liblwgeom/lwgeom_geos_clean.c
@@ -36,7 +36,6 @@
 #include <assert.h>
 
 /* #define PARANOIA_LEVEL 2 */
-#undef LWGEOM_PROFILE_MAKEVALID
 
 LWGEOM* lwcollection_make_geos_friendly(LWCOLLECTION* g);
 LWGEOM* lwline_make_geos_friendly(LWLINE* line);
diff --git a/liblwgeom/profile.h b/liblwgeom/profile.h
new file mode 100644
index 000000000..d4b57e390
--- /dev/null
+++ b/liblwgeom/profile.h
@@ -0,0 +1,17 @@
+#include "liblwgeom.h"
+#include <time.h>
+
+static clock_t start_time, end_time;
+static double cpu_time_used;
+
+/*
+ * A convenience macro for performance testing and breaking
+ * down what time is spent where.
+ */
+
+#define START_PROFILING() do { start_time = clock(); } while(0)
+#define END_PROFILING(name) do { \
+	end_time = clock(); \
+	cpu_time_used = ((double) (end_time - start_time)) / CLOCKS_PER_SEC; \
+	lwnotice("Time used for " #name ": %f secs\n", cpu_time_used); \
+} while(0)

-----------------------------------------------------------------------

Summary of changes:
 NEWS                          |  1 +
 liblwgeom/lwgeom_geos.c       | 29 +++++++++++++++++++----------
 liblwgeom/lwgeom_geos_clean.c |  1 -
 liblwgeom/profile.h           | 17 +++++++++++++++++
 4 files changed, 37 insertions(+), 11 deletions(-)
 create mode 100644 liblwgeom/profile.h


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list