mapbox / mapbox-navigation-android

Mapbox Navigation SDK for Android
https://docs.mapbox.com/android/navigation/overview/
Other
622 stars 319 forks source link

OOM exception building really long routes #4153

Open yunikkk opened 3 years ago

yunikkk commented 3 years ago

Android API:any Mapbox Navigation SDK version:1.4.0

Steps to trigger behavior

  1. Build long route (thousand of kimoleters)
  2. App crashes randomly, depending on memory of the device.

Crash happens within DirectionsJsonObject at GSON serialization with the following stacktrace :

E/AndroidRuntime(11384): java.lang.OutOfMemoryError: Failed to allocate a 3690812 byte allocation with 2202366 free bytes and 2MB until OOM
E/AndroidRuntime(11384):    at java.lang.String.<init>(String.java:400)
E/AndroidRuntime(11384):    at java.lang.AbstractStringBuilder.toString(AbstractStringBuilder.java:633)
E/AndroidRuntime(11384):    at java.lang.StringBuffer.toString(StringBuffer.java:723)
E/AndroidRuntime(11384):    at java.io.StringWriter.toString(StringWriter.java:100)
E/AndroidRuntime(11384):    at com.google.gson.Gson.toJson(Gson.java:639)
E/AndroidRuntime(11384):    at com.google.gson.Gson.toJson(Gson.java:618)
E/AndroidRuntime(11384):    at com.mapbox.api.directions.v5.models.DirectionsJsonObject.toJson(DirectionsJsonObject.java:30)
E/AndroidRuntime(11384):    at com.mapbox.navigation.navigator.internal.MapboxNativeNavigatorImpl$setRoute$2.invokeSuspend(MapboxNativeNavigatorImpl.kt:150)
E/AndroidRuntime(11384):    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
E/AndroidRuntime(11384):    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
E/AndroidRuntime(11384):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
E/AndroidRuntime(11384):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
E/AndroidRuntime(11384):    at java.lang.Thread.run(Thread.java:818)

From my analysis reason is that nav native implementation accepts route as a single string thus fails if string becomes really large. While possible solutions are to pass some Json/Route object entity instead of string, temporary workaround returning some error instead of throwing an exception from background thread would also be nice.

cc @mapbox/navigation-android @mskurydin

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Zayankovsky commented 3 years ago

Reproduced in 2.0.0-beta.21 as well. I used Turn By Turn example on an Android emulator with default settings. Building 3–4 routes from Europe to South Africa is usually enough for me to trigger the crash.

zugaldia commented 3 years ago

Adding it to our next milestone to prioritize an investigation to understand the root cause.

Zayankovsky commented 3 years ago

Hey @mapbox/navnative, currently in order to pass a route to the nav native (e.g. for Navigator.setRoute or Navigator.isDifferentRoute), we have to convert it to a json string. This may lead to OutOfMemoryError if the route is really long and the device has little memory available. Can there be any alternative to this? On Android it looks like we can pass objects directly which can then be treated as jobjects, not sure how that would play on iOS though.

mskurydin commented 3 years ago

@Zayankovsky the alternative would be to make all platforms use our strongly typed objects that the native part may provide and avoid any JSON object parsing in the platform code. However, there is a number of things that should be made first to make it possible.

Zayankovsky commented 3 years ago

@mskurydin is this something we want to eventually come to? If so, we should cut a ticket to discuss it.

zugaldia commented 3 years ago

@Zayankovsky we should explore that option (use NN strongly typed objects) as an additional API (we cannot remove the existing one to avoid breaking SEMVER). Could you cut a NN ticket to track that request?