Skip to content

Geometry toJson() is very slow #932

@cvance

Description

@cvance

Converting a feature's geometry to geojson by calling toJson() can be extremely slow for complex geometries.

Expected Behavior

Convert a complex geometry to geojson in < 100ms

Current Behavior

A 3700 point polygon takes ~646ms, which totals to nearly 2 seconds for us to convert all the geometries of queryRenderedFeatures() to json.

Possible Solution

I've narrowed the issue to the gson serializer, PositionSerializer. It appears creating and tweaking a BigDecimal for each the latitude and longitude is very expensive.

Instead of using PositionSerializer which uses this,

public JsonElement serialize(Position src, Type typeOfSrc, JsonSerializationContext context) {
    JsonArray rawCoordinates = new JsonArray();

    BigDecimal lat = new BigDecimal(src.getLatitude());
    lat = lat.setScale(7, RoundingMode.HALF_UP).stripTrailingZeros();

    BigDecimal lon = new BigDecimal(src.getLongitude());
    lon = lon.setScale(7, RoundingMode.HALF_UP).stripTrailingZeros();

    rawCoordinates.add(new JsonPrimitive(lon));
    rawCoordinates.add(new JsonPrimitive(lat));

    // Includes altitude
    if (src.hasAltitude()) {
      rawCoordinates.add(new JsonPrimitive(src.getAltitude()));
    }

    return rawCoordinates;
  }

I overrode the serialize method to do this:

public JsonElement serialize(Position src, Type typeOfSrc, JsonSerializationContext context) {
           JsonArray rawCoordinates = new JsonArray();
           rawCoordinates.add(trim(src.getLongitude()));
           rawCoordinates.add(trim(src.getLatitude()));
           return rawCoordinates;
       }

       private double trim(double input) {
           return Math.round(input * 100000000D) / 100000000D;
       }

and saw a 10x improvement. My call to get json from queryRenderedFeatures went from 2 seconds to 200ms.

I'm sure there's a more elegant/precise solution that what I've created. Just wanted to point it out for anyone else who's having issues with large/complex geometries being very slow to convert.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions