BLE scan thruput in NCS is low

I have around 140 BLE Scans per second in my environment. I can see them with a NRF52840 with SDK 17 and with an ESP32 as well.

But when I scan using NCS 3.2.2 I only get around 33 scans per second.

I have originally discovered this problem with an NRF54L15, but then switched to NRF52840 for easier verification against the old SDK.

The NCS code is simple and attached below. The configuration file is:

CONFIG_CONSOLE=y
CONFIG_RTT_CONSOLE=y
CONFIG_UART_CONSOLE=n

CONFIG_BT=y
CONFIG_BT_OBSERVER=y

CONFIG_BT_BUF_EVT_RX_COUNT=32
CONFIG_BT_EXT_ADV=y
CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=255

#include <stdio.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/kernel.h>

static uint32_t ble_scans;
static uint32_t ble_scans_last;
static uint32_t ble_scans_bytes;
static uint32_t ble_scans_bytes_last;

#define SCAN_STATS_INTERVAL_SEC 10

static void scan_stats_timer_cb(struct k_timer* timer)
{
	uint32_t count = ble_scans;
	uint32_t delta = count - ble_scans_last;
	ble_scans_last = count;

	uint32_t bytes = ble_scans_bytes;
	uint32_t bytes_delta = bytes - ble_scans_bytes_last;
	ble_scans_bytes_last = bytes;

	printf("BLE Scan: %u scans/s %u bit/s\n", delta / SCAN_STATS_INTERVAL_SEC,
			bytes_delta * 8 / SCAN_STATS_INTERVAL_SEC);
}

K_TIMER_DEFINE(scan_stats_timer, scan_stats_timer_cb, NULL);

static void scan_recv(const struct bt_le_scan_recv_info* info,
					  struct net_buf_simple* buf)
{
	ble_scans++;
	ble_scans_bytes += buf->len;
}

static struct bt_le_scan_cb scan_callbacks = {
	.recv = scan_recv,
};

int scan_ble_start(void)
{
	bt_le_scan_cb_register(&scan_callbacks);

	struct bt_le_scan_param scan_param = {
		.type = BT_LE_SCAN_TYPE_PASSIVE,
		.options = BT_LE_SCAN_OPT_NONE,
		.interval = 0x4000,
		.window = 0x4000,
	};

	int rc = bt_le_scan_start(&scan_param, NULL);
	if (rc) {
		printf("Start scanning failed (%d)\n", rc);
		return rc;
	}

	printf("BLE scanning started (wait %d sec for thruput) ...\n", SCAN_STATS_INTERVAL_SEC);

	k_timer_start(&scan_stats_timer, K_SECONDS(SCAN_STATS_INTERVAL_SEC),
				  K_SECONDS(SCAN_STATS_INTERVAL_SEC));
	return rc;
}

int main(void)
{
	printf("=== BLE Scans per second (%s) ===\n", CONFIG_BOARD_TARGET);

	int rc = bt_enable(NULL);
	if (rc) {
		printf("Bluetooth init failed (%d)\n", rc);
		return rc;
	}

	return scan_ble_start();
}

Related