diff --git a/tests/subsys/settings/performance/CMakeLists.txt b/tests/subsys/settings/performance/CMakeLists.txt new file mode 100644 index 000000000000000..afb5c3d067bdd75 --- /dev/null +++ b/tests/subsys/settings/performance/CMakeLists.txt @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 BayLibre SAS +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(test_settings_perf) + +zephyr_include_directories( + ${ZEPHYR_BASE}/subsys/settings/include + ${ZEPHYR_BASE}/subsys/settings/src + ${ZEPHYR_BASE}/tests/subsys/settings/zms/src + ) + +target_sources(app PRIVATE + settings_test_perf.c) diff --git a/tests/subsys/settings/performance/prj.conf b/tests/subsys/settings/performance/prj.conf new file mode 100644 index 000000000000000..27c208baa0bee7e --- /dev/null +++ b/tests/subsys/settings/performance/prj.conf @@ -0,0 +1,7 @@ +CONFIG_ZTEST=y +CONFIG_FLASH=y +CONFIG_FLASH_MAP=y +CONFIG_ZMS=y + +CONFIG_SETTINGS=y +CONFIG_SETTINGS_RUNTIME=y diff --git a/tests/subsys/settings/performance/settings_test_perf.c b/tests/subsys/settings/performance/settings_test_perf.c new file mode 100644 index 000000000000000..7d492a24e02bd69 --- /dev/null +++ b/tests/subsys/settings/performance/settings_test_perf.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include "settings_priv.h" +#include +#include +#include + +/* This is a test suite for performance testing of settings subsystem by writing + * many small setting values repeatedly. Ideally, this should consume as small + * amount of time as possible for best possible UX. + */ + +static struct k_work_q settings_work_q; +static K_THREAD_STACK_DEFINE(settings_work_stack, 2024); +static struct k_work_delayable pending_store; + +#define TEST_SETTINGS_COUNT (255) +#define TEST_STORE_ITR (5) +#define TEST_TIMEOUT_SEC (60) +#define TEST_SETTINGS_WORKQ_PRIO (1) + +static void bt_scan_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_type, + struct net_buf_simple *buf) +{ + printk("len %u\n", buf->len); +} + +struct test_setting { + uint32_t val; +} test_settings[TEST_SETTINGS_COUNT]; + +K_SEM_DEFINE(waitfor_work, 0, 1); + +static void store_pending(struct k_work *work) +{ + int err; + char path[20]; + struct test_stats { + uint32_t total_calculated; + uint32_t total_measured; + uint32_t single_entry_max; + uint32_t single_entry_min; + } stats = {0, 0, 0, UINT32_MAX}; + + int64_t ts1 = k_uptime_get(); + + /* benchmark storage performance */ + for (int j = 0; j < TEST_STORE_ITR; j++) { + for (int i = 0; i < TEST_SETTINGS_COUNT; i++) { + test_settings[i].val = TEST_SETTINGS_COUNT*j + i; + + int64_t ts2 = k_uptime_get(); + + snprintk(path, sizeof(path), "ab/cdef/ghi/%04x", i); + err = settings_save_one(path, &test_settings[i], + sizeof(struct test_setting)); + zassert_equal(err, 0, "settings_save_one failed %d", err); + + int64_t delta2 = k_uptime_delta(&ts2); + + if (stats.single_entry_max < delta2) { + stats.single_entry_max = delta2; + } + if (stats.single_entry_min > delta2) { + stats.single_entry_min = delta2; + } + stats.total_calculated += delta2; + } + } + + int64_t delta1 = k_uptime_delta(&ts1); + + stats.total_measured = delta1; + + printk("*** storing of %u entries completed ***\n", ARRAY_SIZE(test_settings)); + printk("total calculated: %u, total measured: %u\n", stats.total_calculated, + stats.total_measured); + printk("entry max: %u, entry min: %u\n", stats.single_entry_max, + stats.single_entry_min); + + k_sem_give(&waitfor_work); +} + +ZTEST_SUITE(settings_perf, NULL, NULL, NULL, NULL, NULL); + +ZTEST(settings_perf, test_performance) +{ + int err; + + if (IS_ENABLED(CONFIG_NVS)) { + printk("Testing with NVS\n"); + } else if (IS_ENABLED(CONFIG_ZMS)) { + printk("Testing with ZMS\n"); + } + + k_work_queue_start(&settings_work_q, settings_work_stack, + K_THREAD_STACK_SIZEOF(settings_work_stack), + K_PRIO_COOP(TEST_SETTINGS_WORKQ_PRIO), NULL); + k_thread_name_set(&settings_work_q.thread, "Settings workq"); + k_work_init_delayable(&pending_store, store_pending); + + if (IS_ENABLED(CONFIG_BT)) { + /* enable one of the major subsystems, and start scanning. */ + err = bt_enable(NULL); + zassert_equal(err, 0, "Bluetooth init failed (err %d)\n", err); + + err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, bt_scan_cb); + zassert_equal(err, 0, "Scanning failed to start (err %d)\n", err); + } + + err = settings_subsys_init(); + zassert_equal(err, 0, "settings_backend_init failed %d", err); + + /* fill with values */ + for (int i = 0; i < TEST_SETTINGS_COUNT; i++) { + test_settings[i].val = i; + } + + k_work_reschedule_for_queue(&settings_work_q, &pending_store, K_NO_WAIT); + + err = k_sem_take(&waitfor_work, K_SECONDS(TEST_TIMEOUT_SEC)); + zassert_equal(err, 0, "k_sem_take failed %d", err); + + if (IS_ENABLED(CONFIG_BT)) { + err = bt_le_scan_stop(); + zassert_equal(err, 0, "Scanning failed to stop (err %d)\n", err); + } +} diff --git a/tests/subsys/settings/performance/testcase.yaml b/tests/subsys/settings/performance/testcase.yaml new file mode 100644 index 000000000000000..c0184b9a4da72d0 --- /dev/null +++ b/tests/subsys/settings/performance/testcase.yaml @@ -0,0 +1,61 @@ +tests: + settings.functional.performance.zms: + extra_configs: + - CONFIG_SETTINGS_ZMS=y + - CONFIG_ZMS_LOOKUP_CACHE=y + - CONFIG_ZMS_LOOKUP_CACHE_SIZE=512 + - CONFIG_SETTINGS_ZMS_NAME_CACHE=y + - CONFIG_SETTINGS_ZMS_NAME_CACHE_SIZE=512 + platform_allow: nrf52840dk/nrf52840 nrf54l15dk/nrf54l15/cpuapp qemu_x86 + min_ram: 32 + tags: + - settings + - zms + + settings.functional.performance.nvs: + extra_configs: + - CONFIG_ZMS=n + - CONFIG_NVS=y + - CONFIG_NVS_LOOKUP_CACHE=y + - CONFIG_NVS_LOOKUP_CACHE_SIZE=512 + - CONFIG_SETTINGS_NVS_NAME_CACHE=y + - CONFIG_SETTINGS_NVS_NAME_CACHE_SIZE=512 + platform_allow: nrf52840dk/nrf52840 nrf54l15dk/nrf54l15/cpuapp qemu_x86 + min_ram: 32 + tags: + - settings + - nvs + + settings.functional.performance.zms_bt: + extra_configs: + - CONFIG_BT=y + - CONFIG_BT_OBSERVER=y + - CONFIG_BT_PERIPHERAL=y + - CONFIG_SETTINGS_ZMS=y + - CONFIG_ZMS_LOOKUP_CACHE=y + - CONFIG_ZMS_LOOKUP_CACHE_SIZE=512 + - CONFIG_SETTINGS_ZMS_NAME_CACHE=y + - CONFIG_SETTINGS_ZMS_NAME_CACHE_SIZE=512 + platform_allow: nrf52840dk/nrf52840 nrf54l15dk/nrf54l15/cpuapp qemu_x86 + min_ram: 32 + tags: + - settings + - zms + + settings.functional.performance.nvs_bt: + extra_configs: + - CONFIG_BT=y + - CONFIG_BT_OBSERVER=y + - CONFIG_BT_PERIPHERAL=y + - CONFIG_ZMS=n + - CONFIG_NVS=y + - CONFIG_NVS_LOOKUP_CACHE=y + - CONFIG_NVS_LOOKUP_CACHE_SIZE=512 + - CONFIG_SETTINGS_NVS_NAME_CACHE=y + - CONFIG_SETTINGS_NVS_NAME_CACHE_SIZE=512 + platform_allow: nrf52840dk/nrf52840 nrf54l15dk/nrf54l15/cpuapp qemu_x86 + min_ram: 32 + tags: + - settings + - nvs +