RxAndroidBle: Coroutines — Large NOTIFY gets unbearably slow

Original 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)

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 31 (16 by maintainers)

Most upvoted comments

Ah, indeed you’re right. Multiple sources suggested that writing the descriptor with BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE value will also trigger setCharacteristicNotification() 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!