Opened 49 minutes ago

Last modified 49 minutes ago

#37498 assigned Cleanup/optimization

Improve GEOSGeometry.tuple performance

Reported by: David Smith Owned by: David Smith
Component: GIS Version: dev
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

In ​PR, David has a proof of concept for improving the performance of the GEOSGeometry.tuple property for geometries with many coordinates, from 1.4x - 46x faster depending on the number of coordinates.

Addressing this will make it more practical to use this property when rearchitecting some other geometry construction paths in GeoDjango.


Using one of the fixtures (a Polygon, with 799 coords in one coordinate sequence) from the test suite.

Set up

In [1]: from django.contrib.gis.gdal import DataSource
  ...: from django.contrib.gis.geos import GEOSGeometry
  ...: 
  ...: source = DataSource("tests/gis_tests/data/counties/counties.shp")
  ...: geometry = GEOSGeometry(memoryview(source[0][1].geom.wkb))

Current

In [3]: %timeit geometry.tuple
3.4 ms ± 35.7 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Proposed

In [3]: %timeit geometry.tuple
73.2 μs ± 406 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

A ~46x speedup.

This is a favourable example as it is a single 'large' geometry. The impact will vary depending upon the geometry. A collection of many geometries with each with a small number of coordinates, would perform differently. For example this item from the test suite has 9 sub-geometries with 21 points.

In [1]: import json
  ...: from pathlib import Path
  ...: from django.contrib.gis.geos import GEOSGeometry
  ...: 
  ...: data = json.loads(
  ...:     Path("tests/gis_tests/data/geometries.json").read_text()
  ...: )
  ...: geometry = GEOSGeometry(data["multilinestrings"][1]["wkt"])

Current

In [3]: %timeit geometry.tuple
306 μs ± 3.56 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

Proposed

In [2]: %timeit geometry.tuple
212 μs ± 3.05 μs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

A 1.4x improvement.

Change History (1)

comment:1 by Jacob Walls, 49 minutes ago

Triage Stage: Unreviewed → Accepted
Note: See TracTickets for help on using tickets.
Back to Top