Сбой при создании 10000 объектов в Realm на Android

#android #performance #kotlin #insert #realm

#Android #Производительность #kotlin #вставить #realm

Вопрос:

Я довольно новичок в Android и Kotlin.

У меня есть приложение, которое выполняет некоторые вычисления. Я пытаюсь провести некоторое тестирование производительности. Для этого я хочу создать 10000 объектов:

     Thread().run() {

        try {
            val realm = Realm.getDefaultInstance()

            // Test endedSessions
            val sessions = realm.where<Session>().findAll()
            if (sessions.size < 10) {

                val numberOfSessions = 10000

                realm.beginTransaction()

                for (index in 0..numberOfSessions) {

                    if (index % 1000 == 999) { // added to test and understand when it's crashing
                        Timber.d("****** committing at ${index} sessions...")
                        realm.commitTransaction()
                        realm.beginTransaction()
                    }

                    val session = Session.newInstance(realm, false)

                    // Set Data
                    val calendar = Calendar.getInstance()
                    calendar.set(
                        (2017..2018).random(),
                        (0..11).random(),
                        (0..28).random(),
                        (0..23).random(),
                        (0..59).random()
                    )

                    val startDate = calendar.time
                    calendar.add(Calendar.HOUR_OF_DAY, (2..12).random())
                    calendar.add(Calendar.MINUTE, (0..59).random())
                    val endDate = calendar.time

                    session.startDate = startDate
                    session.endDate = endDate

                    session.result?.let { result ->
                        result.buyin = buyinList.random()
                        result.netResult = resultsList.random()
                    }

                }

                realm.commitTransaction()

            }

            realm.close()
        } catch (e: Exception) {
            Timber.e(e)
        }

    }
  

Проблема в том, что после 5000 сеансов на эмуляторе я получаю следующую ошибку:

I / art: поток [3, tid = 26297, ожидание в цепочке обработки сигналов, поток *= 0x9e560e00, одноранговый узел = 0x12cf79d0, «Перехватчик сигналов»]: реагирует на сигнал 3 A / libc: фатальный сигнал 11 (SIGSEGV), код 1, ошибка addr 0x65726e59 в tid 26292 (alytics.android) I / art: записал трассировки стека в ‘/data/anr/traces.txt «Приложение завершено.

Я не уверен, что это лучшая практика для вставки большого количества объектов в Realm.

Спасибо за вашу помощь!

Комментарии:

1. SIGSEGV означает нарушение памяти. Я предполагаю, что ваш код использует слишком много оперативной памяти в какой-то момент с циклами. Что-нибудь актуальное в /data/anr/traces.txt ?

2. Кстати, вы делаете это commitTransaction() за пределами своего большого цикла. Это означает, что все 10000 транзакций загружаются в память до тех пор, пока не будут сброшены. Может быть причиной.

3. Спасибо за комментарии! Я не уверен, что смотрю на правильный файл трассировок. Я использовал adb для его поиска, и файл всегда заканчивается системным идентификатором sdcard =1796″. Кроме того, в проводнике файлов моего устройства нет каталога «anr».

Ответ №1:

Вы сталкиваетесь с аварийным завершением работы ANR (приложение не отвечает) из-за блокировки основного потока. Основной причиной является эта строка:

 Thread().run() {
  // do work
}
  

Это не делает того, что вы думаете. Это инициализация Thread , а затем выполнение блока кода с этим Thread в качестве получателя. Однако на самом деле это не запуск Thread — вместо этого ваш код выполняется в потоке пользовательского интерфейса.

Вместо этого вам нужно предоставить Runnable вашему потоку и .start его:

 Thread {
  // do your work in here
}.start() // this kicks off the thread and runs the block above asynchronously.
  

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

 Executors.newSingleThreadExecutor().submit { 
  // do your work in here
}