Coroutines — Large NOTIFY gets unbearably slow
See original GitHub issueOriginal topic:
Large NOTIFY gets unbearably slow
Summary
In my project, I’m connecting to a device that transfers a relatively large amount of data (up to 16MB) via a characteristic’s NOTIFY
. The equivalent code on iOS works fine, however on Android, using RxAndroidBle, it slows down to an unbearably slow speed the more data it receives.
MTU is set properly, and ends up being 247 (250 - 3b header), which is the maximum supported on the devices. iOS uses a lower MTU, 162 (165 - 3b header).
I’ve tried requesting lower MTU to see if it helps, to no avail.
The code is pretty simple, after the connection is established (using ReplayingShare
), it creates the subscription via setupNotification
.
The transfer starts out with pretty decent speed, 1MB takes around 1 minute to sync, however around 3MB received, the speed drops, and the next MB takes 2 minutes, the next MB then 3-4 minutes, and the transfer time keeps creeping up.
Initially I thought it was my fault, as I was storing the data the worst possible way:
var rawData = ByteArray(0)
// in the subscribe block:
rawData += it
However even after removing the storage of the data, the slow-down still happens.
Library version
1.10.4
Preconditions
Steps to reproduce actual result
Not sure if it’s reproducible as I have not seen any devices that use a similar technique to transfer data stored on them.
Actual result
The speed of the transfer drops exponentially (or rather, the amount of time required to transfer the same amount of data increases exponentially). The time between the logged Transferred $x out of $y
events also increases (initially it’s around 10-20ms between messages, which increases to around 100-120ms by the time I transferred ~3MB).
Expected result
Speed should be somewhat constant, with minimum variation between the times required to transfer the same sized blocks.
Minimum code snippet reproducing the issue
var transferred = 0
connection
?.flatMap { it.setupNotification(id) }
?.flatMap { it }
?.subscribe(
{
transferred += it.size
logger.i("[DataSync] Transferred $transferred out of $available")
},
{ logger.e(it, "[DataSync] Exception happened") },
{ logger.i("[DataSync] Transfer complete!") }
)
.addToEventStream(eventStream)
Issue Analytics
- State:
- Created 4 years ago
- Comments:31 (16 by maintainers)
Top GitHub Comments
Ah, indeed you’re right. Multiple sources suggested that writing the descriptor with
BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
value will also triggersetCharacteristicNotification()
internally. This is not the case. All is working fine now, I will be reporting back sometime next week to see if this actually improves transfer speeds!Two weeks have passed. I am closing this issue. Still — feel free to share a minimal project that displays the issue — I could then start digging /experimenting from there and reopen the topic. Although it seems not related directly to the library, having experience with coroutines could help in the future or give hints whether a coroutines API is feasible for BLE.