This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Why are notifications slower than indications with SoftDevice s130 on nRF51822?

This question stems from this discussion

 https://devzone.nordicsemi.com/f/nordic-q-a/71044/notifications-how-to-know-who-is-consuming-tx-buffers-most-efficient-way-of-sending-a-sequence-what-error-conditions-are-received

but is so important as a new standard is being based upon behaviors exhibited in actual implementations.

The test situation is a sequence of 87 bytes being indicated/notified as fast as possible with an MTU size of 23. So that means 4 20-bytes chunks followed by one 7-byte chunk are indicated/notified.

  • In the main loop the app is waiting on sd_app_evt_wait()
  • The central peer writes a command to send data
  • sd_app_evt_wait() wakes up
  • App calls sd_ble_evt_get() in a loop
  • If there is an event app calls ble_evt_dispatch(evt) to handle event
  • There is a command to write data so flag to send data is set
  • All events handled app checks send data flag. It is set, app calls sd_ble_gatts_hvx() to send first chunk and clears flag
  • App waits on sd_app_evt_wait() (expecting BLE_GATTS_EVT_HVC [indications] or BLE_EVT_TX_COMPLETE [notifications]
  • Event occurs app wakes up
  • Usual get events, handle event, flag set to send data, next chunk sent, wait for event, etc.

The only thing that changes in the code between the two cases is whether the ble_gatts_hvx_params_t parameter in sd_ble_gatts_hvx() is set for indications versus notifications.

Results with indications: (Times are elapsed time since application start in milliseconds)

APP:DEBUG:=====> Send # 1: Sending 20 bytes of 87 total from offset 0 on attribute handle 0x000E at time 53966
APP:DEBUG:=====> Indication of hunk complete at time 54069, connection handle 0x0000
APP:DEBUG:=====> Send # 1: Sending 20 bytes of 87 total from offset 20 on attribute handle 0x000E at time 54070
APP:DEBUG:=====> Indication of hunk complete at time 54167, connection handle 0x0000
APP:DEBUG:=====> Send # 1: Sending 20 bytes of 87 total from offset 40 on attribute handle 0x000E at time 54167
APP:DEBUG:=====> Indication of hunk complete at time 54264, connection handle 0x0000
APP:DEBUG:=====> Send # 1: Sending 20 bytes of 87 total from offset 60 on attribute handle 0x000E at time 54265
APP:DEBUG:=====> Indication of hunk complete at time 54362, connection handle 0x0000
APP:DEBUG:=====> Send # 1: Sending 7 bytes of 87 total from offset 80 on attribute handle 0x000E at time 54362
APP:DEBUG:=====> Indications complete at time 54459, connection handle 0x0000

Results with notifications:

APP:DEBUG:=====> Send # 1: Sending 20 bytes of 87 total from offset 0 on attribute handle 0x000E at time 29278
APP:DEBUG:Notification TX done event sent
APP:DEBUG:=====> Notification of hunk complete at time 29406, connection handle 0x0000
APP:DEBUG:=====> Send # 1: Sending 20 bytes of 87 total from offset 20 on attribute handle 0x000E at time 29406
APP:DEBUG:Notification TX done event sent
APP:DEBUG:=====> Notification of hunk complete at time 29503, connection handle 0x0000
APP:DEBUG:=====> Send # 1: Sending 20 bytes of 87 total from offset 40 on attribute handle 0x000E at time 29503
APP:DEBUG:Notification TX done event sent
APP:DEBUG:=====> Notification of hunk complete at time 29601, connection handle 0x0000
APP:DEBUG:=====> Send # 1: Sending 20 bytes of 87 total from offset 60 on attribute handle 0x000E at time 29601
APP:DEBUG:Notification TX done event sent
APP:DEBUG:=====> Notification of hunk complete at time 29698, connection handle 0x0000
APP:DEBUG:=====> Send # 1: Sending 7 bytes of 87 total from offset 80 on attribute handle 0x000E at time 29698
APP:DEBUG:Notification TX done event sent
APP:DEBUG:=====> Notification complete at time 29796, connection handle 0x0000

Result without the extra print statement

APP:DEBUG:=====> Send # 1: Sending 20 bytes of 87 total from offset 0 on attribute handle 0x000E at time 10218
APP:DEBUG:=====> Notification of hunk complete at time 10358, connection handle 0x0000
APP:DEBUG:=====> Send # 1: Sending 20 bytes of 87 total from offset 20 on attribute handle 0x000E at time 10358
APP:DEBUG:=====> Notification of hunk complete at time 10455, connection handle 0x0000
APP:DEBUG:=====> Send # 1: Sending 20 bytes of 87 total from offset 40 on attribute handle 0x000E at time 10455
APP:DEBUG:=====> Notification of hunk complete at time 10553, connection handle 0x0000
APP:DEBUG:=====> Send # 1: Sending 20 bytes of 87 total from offset 60 on attribute handle 0x000E at time 10553
APP:DEBUG:=====> Notification of hunk complete at time 10650, connection handle 0x0000
APP:DEBUG:=====> Send # 1: Sending 7 bytes of 87 total from offset 80 on attribute handle 0x000E at time 10650
APP:DEBUG:=====> Notification complete at time 10748, connection handle 0x0000

Note that in all cases, the use of indications results in a faster transfer than notifications. That result is clearly unexpected. I have been asked why I chose to use indications versus notifications in our BT SIG meetings where this standard is being developed. The only reason I did it was to assure that the peer got the data. However, in the field, missing packets has seldom been the problem with health devices. So it was reasonable to use notifications to speed up the transfer since once did not have to wait for the next connection interval. 

So I changed the indications to notifications expecting that transfers would speed up. But they slowed down! Is there something I am doing wrong to get this result or is there some quirk with the SoftDevice TX buffer implementation? I do not think I can justify using indications versus notifications in this standard unless this is a generic result and would be true on all platforms.

Any insight?

Related