Мое приложение собирает значения датчика с акселерометра с максимально возможной частотой дискретизации (~ 200 Гц на моем устройстве) и сохраняет значения в базе данных Room. Я также хочу часто обновлять некоторые графики с последними измерениями, скажем, частотой обновления 5 раз в секунду. С тех пор, как приложение также собирает линейное ускорение (без g) также с частотой ~ 200 Гц (поэтому два датчика каждый с приблизительно 200 Гц, вставляя значения в базу данных), я заметил сильное снижение производительности приложений, и у меня задержка составляет несколько секундмежду собранными значениями ускорения и их отображением на графике. Исходя из профилировщика, я предполагаю, что RxComputationThread является узким местом, так как он активен почти все время из-за Flowables.
Я использую sample (), чтобы ограничить обновления получателя, так как мои графики не должны обновлять супердовольно часто. Это привело к приемлемой производительности, когда я просто собрал один датчик. Я видел, что RxJava предоставляет метод interval () для ограничения частоты излучения со стороны излучателя, но мне это кажется недоступным? (Неразрешенная ссылка).
Может быть, у кого-то есть идеи, как улучшить производительность? Мне нравятся концепции RxJava и Room в целом, и я хотел бы придерживаться их, но я довольно сильно застрял на этом этапе.
Вот код, который я использую для наблюдения таблицы Room SQL и обновления графиков:
// Observe changes to the datasource and create a new subscription if necessary
sharedViewModel.dataSource.observe(viewLifecycleOwner, Observer { source ->
Log.d("TAG", "Change observed!")
when (source) {
"acc" -> {
val disposableDataSource =
sharedViewModel.lastSecondsAccelerations
.sample(200, TimeUnit.MILLISECONDS)
.onBackpressureDrop()
.subscribeOn(Schedulers.io())
.subscribe { lastMeasurements ->
Log.d("TAG", Thread.currentThread().name)
if (sharedViewModel.isReset.value == true && lastMeasurements.isNotEmpty()) {
val t =
lastMeasurements.map { (it.time.toDouble() * 1e-9) - (lastMeasurements.last().time.toDouble() * 1e-9) }
val accX = lastMeasurements.map { it.accX.toDouble() }
val accY = lastMeasurements.map { it.accY.toDouble() }
val accZ = lastMeasurements.map { it.accZ.toDouble() }
// Update plots
updatePlots(t, accX, accY, accZ)
}
}
compositeDisposable.clear()
compositeDisposable.add(disposableDataSource)
}
"lin_acc" -> {
val disposableDataSource =
sharedViewModel.lastSecondsLinAccelerations
.sample(200, TimeUnit.MILLISECONDS)
.onBackpressureDrop()
.subscribeOn(Schedulers.io())
.subscribe { lastMeasurements ->
Log.d("TAG", Thread.currentThread().name)
if (sharedViewModel.isReset.value == true && lastMeasurements.isNotEmpty()) {
val t =
lastMeasurements.map { (it.time.toDouble() * 1e-9) - (lastMeasurements.last().time.toDouble() * 1e-9) }
val accX = lastMeasurements.map { it.accX.toDouble() }
val accY = lastMeasurements.map { it.accY.toDouble() }
val accZ = lastMeasurements.map { it.accZ.toDouble() }
// Update plots
updatePlots(t, accX, accY, accZ)
}
}
compositeDisposable.clear()
compositeDisposable.add(disposableDataSource)
}
}
})
Запрос на получение последних 10 секунд измерений
@Query("SELECT * FROM acc_measurements_table WHERE time > ((SELECT MAX(time) from acc_measurements_table)- 1e10)")
fun getLastAccelerations(): Flowable<List<AccMeasurement>>