【发布时间】:2019-11-07 21:30:41
【问题描述】:
我的应用正在以可能的最高采样率(在我的设备上约为 200 Hz)从加速度计收集传感器值,并将这些值保存在 Room 数据库中。我还想经常用最新的测量值更新一些图表,比如说每秒 5 次的刷新率。自从该应用程序还收集了大约 200 Hz 的线性加速度(没有 g)(因此两个传感器每个都以大约 200Hz 的频率将值插入数据库),我注意到应用程序性能大幅下降,我有几秒钟的延迟在收集的加速度值和它们显示在图中的值之间。 根据分析器,我的猜测是 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>>
【问题讨论】:
-
只是一个想法,映射是否会成为问题的根源(对于足够大的列表)?也许它发生在主线程上,因为逻辑在 subscribe { ... } 中。 RxJava 有一个 map 操作符
-
另一个想法,也许 Room 是瓶颈。这是很多插入和查询。你能找出问题所在吗?
-
我一直在研究 Room v Traiditonal SQLite 的性能,使用 Room 时似乎至少有 20% 的开销。例如传统的
Run ALL From 2019-11-07 22:16:31 To 2019-11-07 22:19:28 Elapsed = 5882和使用 RoomRun ALL From 2019-11-07 22:17:12 To 2019-11-07 22:18:23 Elapsed = 7449的相同 10 次运行(Elapsed 可能是错误的术语,它是数据库访问所用时间的累积)。 -
但是,慢 20% 的概率并不意味着从平滑变为波涛汹涌。 1)如果您从 subscribe { ... } 中删除代码(即留空)会发生什么情况 2)结帐背压策略,也许是一些有趣的事情
-
很抱歉,我需要更多信息来回答您。为什么要从 Room 数据库中读取数据?您不能直接访问传感器吗?你不能直接从传感器读取吗?我认为将所有这些数据通过 Room 传输给海豚展示它们并不是一个好主意。另外,您是否需要将它们保存到本地数据库中,或者您就是这样做的?
标签: android kotlin rx-java android-room