Парсинг крошечных JSON из android ресурсов невероятно медленен - PullRequest
0 голосов
/ 14 января 2020

Я пишу простое Android приложение на Kotlin, которое будет показывать молитвы, разделенные на категории для пользователя. В папке активов находится 5 JSON файлов, каждый из которых имеет около 10 КиБ.

Я использую Klaxon для анализа файлов JSON в этих двух классах данных:

data class Prayer(val prayerName: String, val verseTitle: String, val verseBody: String,
              val prayerLine: String, val prayerBody: String, val prayerEnding: String)

data class PrayerCategory(val title: String, val bgImage: String, val headerImage: String,
                      val prayers : List<Prayer>)

Вот код, который я использую для разбора молитв:

private fun loadPrayerNames(jsonFile: String) {
    val millis = measureTimeMillis {
        val input = assets.open("${jsonFile}.json")
        val prayerCategory = Klaxon().parse<PrayerCategory>(input)

        if (prayerCategory != null) {
            for (prayer in prayerCategory.prayers) {
                val prayerName = prayer.prayerName
                prayersMap[prayerName] = prayer
            }
        }
    }

    println("Loading prayer category took $millis ms.")
}

Как видите, существует только один доступ к ресурсам. Нет assets.list (), не фигня. И, как вы заметили, я измерил время ... сделайте ваши предположения .. Вот отладочный вывод:

Загрузка категории молитвы заняла 3427 мс.

Да, вот так. Загрузка и разбор 10KiB большой JSON занял 3,5 секунды! Повторюсь. Нет ракетостроения. Просто разбор 10 КиБ JSON. 3,5 секунды ..... Хм ..

Кстати, я тестирую его на Nokia 6.1, довольно симпатичном телефоне.

Итак ... мои вопросы:

  1. Что вызывает такое поведение?
  2. Есть ли способ ускорить это, кроме создания базы данных для хранения около 50 молитв?

Я буду очень благодарен за вашу помощь!

1 Ответ

0 голосов
/ 14 января 2020

Android активы, кажется, имеют плохую репутацию, когда дело доходит до производительности. Тем не менее, мое тестирование показало, что в этой ситуации ответственность за это была библиотека Klaxon.

После обнаружения основной проблемы с производительностью в Klaxon (см. https://github.com/cbeust/klaxon/issues/154), которая до сих пор не устранена, Я попробовал рекомендуемую альтернативу: Moshi (https://github.com/square/moshi).

Moshi действительно улучшил производительность, но анализ моего JSON все же занял около 1 секунды.

После этих эксперименты, я прибегнул к старому доброму синтаксическому анализу, используя JSONObject:

data class Prayer(val prayerName: String, val verseTitle: String, val verseBody: String,
                val prayerLine: String, val prayerBody: String, val prayerEnding: String) {
    companion object {
        fun parseJson(json: JSONObject) : Prayer = Prayer(json.getString("prayerName"),
                json.getString("verseTitle"),  json.getString("verseBody"),
                json.getString("prayerLine"),  json.getString("prayerBody"),
                json.getString("prayerEnding"))

    }
}

data class PrayerCategory(val title: String, val bgImage: String, val headerImage: String,
                        val prayers : List<Prayer>) {
    companion object {
        fun parseJson(json: JSONObject): PrayerCategory {
            val prayers = ArrayList<Prayer>()
            val prayersArray = json.getJSONArray("prayers")

            for(i in 0 until prayersArray.length()) {
                prayers.add(Prayer.parseJson(prayersArray.getJSONObject(i)))
            }

            return PrayerCategory(json.getString("title"), json.getString("bgImage"),
                json.getString("headerImage"), prayers)
        }
    }
}

Это сократило время синтаксического анализа с 3427 мс до 13 мс. Дело закрыто. ; -)

...