JuliaGeo / GeoJSON.jl

Utilities for working with GeoJSON data in Julia
https://juliageo.org/GeoJSON.jl/stable/
MIT License
68 stars 10 forks source link

Fix coord order and performance of `write` #64

Closed rafaqz closed 1 year ago

rafaqz commented 1 year ago

Similar to #57 but with the new updates.

Fixes point order to be always X, Y, (Z), and uses Vectors of NTuple rather than GI.coordinates to reduce allocation and improve type stability.

The performance is still not amazing, I feel like we could use some kind of lazy array of NTuple to stream from geometries strait to string rather than allocating the intermediate arrays.

using GeoJSON
using BenchmarkTools
using GeometryBasics
using ArchGDAL
import GeoInterface as GI
include("geojson_samples.jl")

g = GI.geometry(GeoJSON.read(Samples.features[4]))
g1 = GI.convert(ArchGDAL, g)
g2 = GI.convert(GeometryBasics, g)
g3 = GI.convert(GI, g)

# This branch

julia> @btime GeoJSON.write($g)
  1.026 μs (13 allocations: 1.40 KiB)
"{\"type\":\"MultiLineString\",\"coordinates\":[[[3.75,9.25],[-130.95,1.52]],[[23.15,-34.25],[-1.35,-4
.65],[3.45,77.95]]]}"

julia> @btime GeoJSON.write($g1)
  3.316 μs (50 allocations: 4.82 KiB)
"{\"type\":\"Polygon\",\"coordinates\":[[[3.75,9.25],[-130.9499969482422,1.5199999809265137]],[[23.149
999618530273,-34.25],[-1.350000023841858,-4.650000095367432],[3.450000047683716,77.94999694824219]]]}"

julia> @btime GeoJSON.write($g2)
  1.435 μs (24 allocations: 4.37 KiB)
"{\"type\":\"Polygon\",\"coordinates\":[[[3.75,9.25],[-130.9499969482422,1.5199999809265137]],[[23.149
999618530273,-34.25],[-1.350000023841858,-4.650000095367432],[3.450000047683716,77.94999694824219]]]}"

julia> @btime GeoJSON.write($g3)
  1.789 μs (24 allocations: 1.51 KiB)
"{\"type\":\"Polygon\",\"coordinates\":[[[3.75,9.25],[-130.95,1.52]],[[23.15,-34.25],[-1.35,-4.65],[3.
45,77.95]]]}"

# main

julia> @btime GeoJSON.write($g)
  1.029 μs (13 allocations: 1.40 KiB)
"{\"type\":\"MultiLineString\",\"coordinates\":[[[3.75,9.25],[-130.95,1.52]],[[23.15,-34.25],[-1.35,-4
.65],[3.45,77.95]]]}"

julia> @btime GeoJSON.write($g1)
  11.873 μs (74 allocations: 5.91 KiB)
"{\"type\":\"Polygon\",\"coordinates\":[[[3.75,9.25],[-130.9499969482422,1.5199999809265137]],[[23.149
999618530273,-34.25],[-1.350000023841858,-4.650000095367432],[3.450000047683716,77.94999694824219]]]}"

julia> @btime GeoJSON.write($g2)
  2.799 μs (28 allocations: 4.59 KiB)
"{\"type\":\"Polygon\",\"coordinates\":[[[3.75,9.25],[-130.9499969482422,1.5199999809265137]],[[23.149
999618530273,-34.25],[-1.350000023841858,-4.650000095367432],[3.450000047683716,77.94999694824219]]]}"

julia> @btime GeoJSON.write($g3)
  2.253 μs (12 allocations: 1.01 KiB)
"{\"type\":\"Polygon\",\"coordinates\":[[[3.75,9.25],[-130.95,1.52]],[[23.15,-34.25],[-1.35,-4.65],[3.
45,77.95]]]}"
rafaqz commented 1 year ago

Looks like we need more tests on write from other geometry types. I might implement GeoInterface.convert for Feature and FeatureCollection to make that easier to do first.

visr commented 1 year ago

Looks good, nice speedup and fix! The extra converts would be good, in a separate PR I assume.

rafaqz commented 1 year ago

Yeah I guess it can wait