Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Geometry toJson() is very slow #932

Closed
cvance opened this issue Dec 1, 2018 · 1 comment · Fixed by #938
Closed

Geometry toJson() is very slow #932

cvance opened this issue Dec 1, 2018 · 1 comment · Fixed by #938

Comments

@cvance
Copy link

cvance commented Dec 1, 2018

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.

@osana
Copy link
Contributor

osana commented Dec 3, 2018

@cvance thank you for reporting this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants