mapbox / mapbox-maps-android

Interactive, thoroughly customizable maps in native Android powered by vector tiles and OpenGL.
https://www.mapbox.com/mobile-maps-sdk
Other
466 stars 131 forks source link

OutOfMemoryException for FeatureCollection.fromFeatures() #1721

Closed damianvisser closed 1 year ago

damianvisser commented 1 year ago

Environment

Observed behavior and steps to reproduce

Mapbox crashes when making featureCollection from too many features.

Steps to reproduce:

  1. Create 240000 features in a list
  2. Do call FeatureCollection.fromFeatures(listOfFeatures)

Creating of feature on our side:

Feature.fromGeometry( point ).apply { addStringProperty(ID_FEATURE_PROPERTY, id) addStringProperty(MAP_MARKER_TYPE_FEATURE_PROPERTY, toMapMarkerType().name) addNumberProperty(LONGITUDE_FEATURE_PROPERTY, point.longitude()) addNumberProperty(LATITUDE_FEATURE_PROPERTY, point.latitude()) }

Expected behavior

FeatureCollection.fromFeatures() should not get out of memory for 240.000 features. It's only 15 MB

Notes / preliminary analysis

I think you can use the Gson streaming API to stream the data, instead of trying to load it all at once with Gson.toJson().

Additional links and references

java.lang.OutOfMemoryError: Failed to allocate a 150994952 byte allocation with 84761584 free bytes and 80MB until OOM, target footprint 268435456, growth limit 268435456 at java.util.Arrays.copyOf(Arrays.java:3766) at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:125) at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:542) at java.lang.StringBuffer.append(StringBuffer.java:350) at java.io.StringWriter.write(StringWriter.java:122) at com.google.gson.stream.JsonWriter.string(JsonWriter.java:590) at com.google.gson.stream.JsonWriter.writeDeferredName(JsonWriter.java:401) at com.google.gson.stream.JsonWriter.value(JsonWriter.java:416) at com.google.gson.internal.bind.TypeAdapters$29.write(TypeAdapters.java:746) at com.google.gson.internal.bind.TypeAdapters$29.write(TypeAdapters.java:760) at com.google.gson.internal.bind.TypeAdapters$29.write(TypeAdapters.java:698) at com.google.gson.internal.bind.TypeAdapters$35$1.write(TypeAdapters.java:890) at com.mapbox.geojson.Feature$GsonTypeAdapter.write(Feature.java:568) at com.mapbox.geojson.Feature$GsonTypeAdapter.write(Feature.java:497) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:97) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61) at com.mapbox.geojson.FeatureCollection$GsonTypeAdapter.write(FeatureCollection.java:328) at com.mapbox.geojson.FeatureCollection$GsonTypeAdapter.write(FeatureCollection.java:278) at com.google.gson.Gson.toJson(Gson.java:704) at com.google.gson.Gson.toJson(Gson.java:683) at com.google.gson.Gson.toJson(Gson.java:638) at com.google.gson.Gson.toJson(Gson.java:618) at com.mapbox.geojson.FeatureCollection.toJson(FeatureCollection.java:223) at com.mapbox.maps.extension.style.utils.TypeUtilsKt.toValue(TypeUtils.kt:329) at com.mapbox.maps.extension.style.sources.generated.GeoJsonSource.toPropertyValue(GeoJsonSource.kt:331) at com.mapbox.maps.extension.style.sources.generated.GeoJsonSource.applyGeoJsonData$lambda-11$lambda-10(GeoJsonSource.kt:353) at com.mapbox.maps.extension.style.sources.generated.GeoJsonSource.$r8$lambda$_9l_l-ZA5tTLYApH7jbY6OB3HUI(Unknown Source:0) at com.mapbox.maps.extension.style.sources.generated.GeoJsonSource$$ExternalSyntheticLambda1.run(Unknown Source:4) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.os.HandlerThread.run(HandlerThread.java:67)

kiryldz commented 1 year ago

Fixed starting from v10.11 version.