[Compose Extension] OOM crash in GeoJsonSourceState when data contains large feature list
まだ誰も着手していません。
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 76/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 静か
- 領域
- mobile, performance
調査の方向性
まず extension-compose/src/main/java/com/mapbox/maps/extension/compose/style/sources/SourceState.kt の 230 行目付近にある launchCollectGeoJsonData から始め、次に PropertyTypes.kt の GeoJSONData.toString() を調べます。大きな GeoJSONData の feature リストで再現し、source の更新時に feature リスト全体の文字列を構築しようとしたり、OutOfMemoryError でクラッシュしたりしなくなったことを確認します。
索引モデルが issue の本文から書いたものです。
説明
Environment
- Android OS version: Any (lower-end devices with smaller growth limits hit it sooner)
- Devices affected: Any. Reproducible when the GeoJSON feature list is sufficiently large (crash observed at ~143 MB allocation attempt with a 201 MB growth limit)
- Maps SDK Version: Confirmed present on main as of the date of this report.
Observed behavior and steps to reproduce
App crashes with OutOfMemoryError when a GeoJsonSourceState is backed by a GeoJSONData(List) containing a large number of features, due to an internal log call.
Steps:
- Create a
GeoJsonSourceState->sourceState.data = GeoJSONData(listOfFeatures). - Observe the app crash with the following OOM.
val sourceState = remember(sourceId) {
GeoJsonSourceState(sourceId = sourceId).apply {
...
}
}
LaunchedEffect(features) {
withContext(Dispatchers.Default) {
val finalFeatures = features.map { it.toMapboxFeature() }
sourceState.data = GeoJSONData(finalFeatures)
}
}
sourceState
Stack trace:
java.lang.OutOfMemoryError: Failed to allocate a 143240712 byte allocation with 25165824 free bytes and 49MB until OOM, target footprint 174756928, growth limit 201326592
at java.util.Arrays.copyOf(Arrays.java:3766)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:125)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:449)
at java.lang.StringBuilder.append(StringBuilder.java:137)
at java.lang.StringBuilder.append(StringBuilder.java:132)
at java.util.AbstractCollection.toString(AbstractCollection.java:473)
at com.mapbox.maps.extension.compose.style.sources.GeoJSONData.toString(PropertyTypes.kt:335)
at java.lang.String.valueOf(String.java:3657)
at java.lang.StringBuilder.append(StringBuilder.java:132)
at com.mapbox.maps.extension.compose.style.sources.SourceState$launchCollectGeoJsonData$1.invokeSuspend(SourceState.kt:230)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.java:34)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:100)
at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:124)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:89)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:586)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.execTask(CoroutineScheduler.kt:798)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:798)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:717)
Suppressed:
kotlinx.coroutines.internal.DiagnosticCoroutineContextException:
[CoroutineName(SourceStateMapboxMapScope_gps_source),
StandaloneCoroutine{Cancelling}@5888d8a,
Dispatchers.IO]
Expected behavior
GeoJsonSourceState should handle large feature collections without crashing. Updating a source with thousands of GPS points is a standard use case. The SDK should not attempt to serialize the full feature list into a single String as a side-effect of a log call.
Notes / preliminary analysis
SourceState.kt:230 eager toString() in a log statement
// SourceState.kt ~line 228-233
private fun CoroutineScope.launchCollectGeoJsonData(mapboxMap: MapboxMap) =
launch(Dispatchers.IO) {
geoJSONDataChannel.consumeEach { data ->
logD(TAG, "setGeoJsonSourceData: $data") // <-- triggers toString() unconditionally
...
}
}
Additional links and references
SourceState.kt — launchCollectGeoJsonData
(https://github.com/mapbox/mapbox-maps-android/blob/main/extension-compos
e/src/main/java/com/mapbox/maps/extension/compose/style/sources/SourceSta
te.kt)
PropertyTypes.kt — GeoJSONData.toString()
(https://github.com/mapbox/mapbox-maps-android/blob/main/extension-compos
e/src/main/java/com/mapbox/maps/extension/compose/style/sources/PropertyT
ypes.kt)
- 主要言語
- Kotlin
- スター
- 578
- フォーク
- 163
- PR マージ指標
- 30日以内にマージされた PR はありません
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
mapbox/mapbox-maps-android のほかの issue
-
bug :beetle:
難易度 5/5 1週間以上 初心者へのやさしさ 22/100
mapbox/mapbox-maps-android#2734 · リアクション 1 件 ·
-
難易度 4/5 3〜5日 初心者へのやさしさ 48/100
mapbox/mapbox-maps-android#2733 ·
-
bug :beetle:
難易度 4/5 3〜5日 初心者へのやさしさ 50/100
mapbox/mapbox-maps-android#2732 ·
-
auto-triaged bug :beetle:
難易度 4/5 3〜5日 初心者へのやさしさ 45/100
mapbox/mapbox-maps-android#2731 · リアクション 4 件 ·
-
bug :beetle:
難易度 4/5 3〜5日 初心者へのやさしさ 48/100
mapbox/mapbox-maps-android#2730 ·
mapbox/mapbox-maps-android の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 64/100
maplibre/maplibre-native-ffi#792 ·
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 74/100
メンテナーはふだん 1 日以内に返信
-
an:enhancement
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 74/100
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100