Optimizing memory usage in Matter applications
You can use different approaches to optimizing the memory usage of your Matter application, both on the nRF Connect SDK side and in the Matter SDK.
Reducing memory usage on the nRF Connect SDK side
See the Memory footprint optimization guide for information about how to reduce memory usage for the nRF Connect SDK generally and for specific subsystems in particular, including Bluetooth® LE, Matter, and Thread.
Cutting off log regions for Matter SDK modules
The Matter SDK, included in the nRF Connect SDK as one of the submodule repositories using a dedicated Matter fork, provides a custom mechanism for optimizing memory usage in a Matter application. This solution defines a series of logging modules, each of which is a logical section of code that is a source of log messages and can include one or more files. For the complete list of modules, see the Matter SDK’s LogModule enumeration.
You can reduce the memory usage of each of these modules in the following ways:
Define a custom logging level for each module by setting one of the Matter SDK logging levels (Error, Progress, Detail, or Automation) in
src/chip_project_config.h
, located in your application’s directory. For example, the following snippet shows the Bluetooth LE module set to logging at the Detail level:CHIP_CONFIG_LOG_MODULE_Ble_DETAIL 1
Turn off logging for any of the modules by setting its respective enabler to
0
in the Matter SDK’s LogModule enumeration. For example, the following snippet shows the Bluetooth LE module cut off from logging its entries:CHIP_CONFIG_LOG_MODULE_Ble 0
Enabling Link Time Optimization (LTO)
You can reduce the memory usage of your Matter application by enabling Link Time Optimization (LTO).
LTO is an advanced compilation technique that performs optimization across all compiled units of an application at the link stage, rather than within each unit separately.
To enable LTO, set the CONFIG_LTO
and CONFIG_ISR_TABLES_LOCAL_DECLARATION
Kconfig options to y
.
Note
Support for Link Time Optimization is experimental.
Profiling memory in Matter applications
This section offers useful commands for measuring usage of stacks, heaps, and Zephyr settings, and Kconfig options for configuring their memory size. Measuring memory usage allows you to adjust these values according to your project’s requirements.
Measuring memory usage
You can obtain the current memory statistics from the device using Kconfig options and UART shell commands.
To do this, set the CONFIG_CHIP_MEMORY_PROFILING
global Matter memory profiling Kconfig to y
.
This activates all the other necessary Kconfig options and enables all UART shell commands for measuring memory usage.
Alternatively, you can enable each option separately.
The Kconfig option enables the following functionalities on the Matter device:
Matter Settings shell commands by setting the
CONFIG_NCS_SAMPLE_MATTER_SETTINGS_SHELL
Kconfig option toy
.Using CLI in nRF Connect examples by setting the
CONFIG_CHIP_LIB_SHELL
Kconfig option toy
.Zephyr Kernel commands by setting the
CONFIG_KERNEL_SHELL
Kconfig option toy
.Zephyr Settings shell by setting the
CONFIG_SETTINGS_SHELL
Kconfig option toy
.OpenThread shell by setting the
CONFIG_OPENTHREAD_SHELL
Kconfig option toy
if you build the Matter over Thread variant.Matter statistics shell by setting the
CONFIG_CHIP_STATISTICS
Kconfig option toy
.
All the functionalities listed below are automatically enabled if the Matter memory profiling Kconfig option is activated. However, you can also find the specific Kconfig options required for each functionality to enable them separately.
Non-Volatile Storage (NVS) Settings usage
You can measure the NVS Settings usage by monitoring peak and current usage.
To do this, you need to set the following in your application prj.conf
file:
CONFIG_SHELL=y
CONFIG_NCS_SAMPLE_MATTER_SETTINGS_SHELL=y
CONFIG_SHELL_MINIMAL=n
CONFIG_SETTINGS_SHELL=y
The NVS Settings usage may change during the device’s lifetime.
The settings_storage
partition can only be changed by reflashing the Matter device.
This means that it cannot be altered through DFU (Device Firmware Update).
Because of this, you need to be careful when setting the partition, and should allocate some free space to ensure that it can accommodate more data in the future.
The data used within this partition may increase with updates to Matter and the nRF Connect SDK.
If this functionality is enabled, you can use Matter Settings shell commands.
To see the full list of available commands, use the following UART shell command on your device:
uart:~$ matter_settings
You will see a list of the available commands like this one:
peak : Print peak settings size in Bytes. This size is reset during
reboot.
Usage: matter_settings peak
reset : Reset peak settings size in Bytes.
Usage: matter_settings reset
get_size : Get size of the chosen settings entry.
Usage: matter_settings get_size <name>
current : Get current settings size in Bytes.
Usage: matter_settings current
free : Get free settings space in Bytes.
Usage: matter_settings free
Similarly to heap measurements, you can reset the current peak usage value, read the peak value, perform some operations on the device, and read the peak value again to obtain the difference.
Reset the peak usage value:
uart:~$ matter_settings reset
Measure the peak usage:
uart:~$ matter_settings peak
Perform some operations on your device.
Read the current peak usage again using the
matter_settings peak
command again.The difference between the current peak value and the value in Step 2 shows the peak usage.
The matter_settings
command also allows you also to read the current value of Zephyr settings usage.
To read it from the device, use the following UART shell command on your device:
uart:~$ matter_settings current
You can also read the size of a specific settings entry by calling the matter_settings get_size <name>
UART shell command on your device.
To obtain the name of an entry, you can use the settings list
command from the settings
UART shell command set.
To read the size of a specific settings entry, complete the following steps:
View the list of all available settings:
uart:~$ settings list
mt/g/im/ec mt/g/gdc mt/g/gcc mt/g/lkgt mt/ctr/reboot-count mt/cfg/unique-id its/0000000000020001
Choose one of the available keys, for example
mt/ctr/reboot-count
to read size of the reboot counter.Read the size of the chosen key:
matter_settings get_size mt/ctr/reboot-count
To learn about other settings
UART shell commands, use the following UART shell command on your device:
uart:~$ settings
You will see subcommand descriptions like the following:
settings - Settings shell commands
Subcommands:
list : List all settings in a subtree (omit to list all)
Usage: settings list [subtree]
read : Read a specific setting
Usage: settings read [type] <name>
type: string or hex (default: hex)
write : Write to a specific setting
Usage: settings write [type] <name> <value>
type: string or hex (default: hex)
delete : Delete a specific setting
Usage: settings delete <name>
Note
The Matter Settings shell commands provide only the peak value of the current settings usage.
To estimate the space needed for the settings_storage
partitions, gather the size of each settings key and decide how often the value is updated during the device’s lifetime.
Stack usage for all threads
You can measure the stack usage by monitoring peak usage of each thread stack.
To do this, you need to set the following in your application prj.conf
file:
CONFIG_SHELL=y
CONFIG_KERNEL_SHELL=y
You can also measure the peak stack usage of each thread running on the Matter device. This measurement can help in setting the proper stack size value and saving RAM space for other stacks or the heap.
To see all statistics for each running thread, use the following UART shell command on your device:
kernel stacks
You will see statistics similar to the following ones, although the number of threads may be different:
0x20011568 CHIP (real size 6144): unused 3952 usage 2192 / 6144 (35 %)
0x200069e8 BT RX WQ (real size 1216): unused 1040 usage 176 / 1216 (14 %)
0x20006930 BT TX (real size 1536): unused 1080 usage 456 / 1536 (29 %)
0x20006d08 rx_q[0] (real size 1536): unused 1384 usage 152 / 1536 ( 9 %)
0x20006e18 openthread (real size 4096): unused 3432 usage 664 / 4096 (16 %)
0x20007be8 ot_radio_workq (real size 1024): unused 848 usage 176 / 1024 (17 %)
0x20006768 shell_uart (real size 3200): unused 2104 usage 1096 / 3200 (34 %)
0x20002580 nrf5_rx (real size 1024): unused 832 usage 192 / 1024 (18 %)
0x2000d510 sysworkq (real size 1152): unused 880 usage 272 / 1152 (23 %)
0x20007b10 MPSL Work (real size 1024): unused 808 usage 216 / 1024 (21 %)
0x2000d3a0 idle (real size 320): unused 272 usage 48 / 320 (15 %)
0x2000d458 main (real size 6144): unused 4584 usage 1560 / 6144 (25 %)
0x20025d00 IRQ 00 (real size 2048): unused 1120 usage 928 / 2048 (45 %)
You can read the peak usage measurement for each thread and learn about the total size of the stack, and unused bytes. You can adjust the stack values for your application using estimations based on these measurements.
Configuring memory usage
Most of the Matter samples in the nRF Connect SDK have a safe configuration that assumes a high number of free space for heap, stacks, and settings partition size. After measuring the memory usage, you may want to adjust the memory parameters according to your project’s requirements.
The following sections present a guide on how to adjust specific maximum memory values.
Settings usage
Important
The settings_storage
partition can only be changed by reflashing the Matter device.
This means that it cannot be altered through DFU (Device Firmware Update).
Because of this, you need to be careful when setting the partition, and should allocate some free space to ensure that it can accommodate more data in the future.
The data used within this partition may increase with updates to Matter and the nRF Connect SDK.
To adjust the settings usage, you need to modify the pm_static
file related to your target board.
For example, to modify the settings_storage
partition in the Matter Template sample for the nrf52840dk_nrf52840
target, complete the following steps:
Locate the
pm_static_nrf52840dk_nrf52840.yml
in the sample directoryLocate the
settings_storage
partition within thepm_static
file.For example:
settings_storage: address: 0xf8000 size: 0x8000 region: flash_primary
Modify the
size
value.Align all other partitions to not overlap any memory regions.
To learn more about how to configure partitions in the
pm_static
file, see the Partition Manager documentation.Align the
CONFIG_SETTINGS_NVS_SECTOR_COUNT
Kconfig option value to the used NVS sectors. Each target in nRF Connect SDK Matter samples uses 4 kB NVS sectors, so you can divide thesettings_storage
partition size by 4096 (0x1000) to get the value you need to set for theCONFIG_SETTINGS_NVS_SECTOR_COUNT
Kconfig option.
To learn more about partitioning, see the Partition layout guide.
Stack sizes for all threads
Each thread has its own Kconfig option to configure the maximum stack size. You can modify Kconfig values to increase or decrease the maximum stack sizes according to your project’s requirements.
The following table presents the possible threads used in a Matter application and the Kconfig options dedicated to setting the maximum stack usage for each of them:
Thread name |
Kconfig option |
Description of the related stack |
CHIP |
Matter thread stack.
For example, all functions scheduled to be execute from
the Matter thread context using
the |
|
openthread |
OpenThread thread stack. For Matter over Thread only. |
|
main |
Application thread stack.
For example, all functions scheduled to be execute from
the Main thread context using
the |
|
idle |
The Idle thread that work while any other thread is not working. |
|
MPSL Work |
Multiprotocol Service Layer libraries thread stack. Switching times slots for multi-protocol purposes. |
|
sysworkq |
Zephyr stack. Switching context purposes. |
|
shell_uart |
Zephyr shell purposes. |
|
BT TX |
Bluetooth LE transmitting thread stack. |
|
nrf5_rx |
Bluetooth LE receiving thread stack. |
|
BT RX WQ |
Bluetooth LE processing thread stack. |
|
ot_radio_workq |
IEEE 802.15.4 radio processing thread stack. For Matter over Thread only. |
|
net_mgmt |
Zephyr network management event processing thread stack. For Matter over Wi-Fi only. |
|
wpa_supplicant_main |
WPA supplicant main thread. Processing Wi-Fi requests and connections. For Matter over Wi-Fi only. |
|
wpa_supplicant_wq |
WPA supplicant work queue thread. Processing Wi-Fi task queue For Matter over Wi-Fi only. |
|
nrf700x_bh_wq |
nRF700x Wi-Fi driver work queue. |
|
nrf700x_intr_wq |
Interrupts processing generated by the nRF700X Wi-Fi radio. |
|
mbox_wq |
Inter Processor Communication. For multi-processors targets only. |
Heap size
The Matter application defines the static size of the heap used by all memory allocations.
This configuration ignores the CONFIG_HEAP_MEM_POOL_SIZE
Kconfig option value in the application configuration.
The static size is determined by the CONFIG_CHIP_MALLOC_SYS_HEAP
and CONFIG_CHIP_MALLOC_SYS_HEAP_OVERRIDE
Kconfig options.
To use a dynamic heap size on your Matter device, set them both to n
.
The static heap size means that you can define the maximum heap size for your application by setting the CONFIG_CHIP_MALLOC_SYS_HEAP_SIZE
Kconfig value.
You can also adjust the heap dedicated for MbedTLS purposes by setting the CONFIG_MBEDTLS_HEAP_SIZE
Kconfig option value.
Memory profiling troubleshooting
When you manipulate memory sizes, your device can experience issues and faults. Many of these issues can be caused by incorrect stack or heap configurations. The following can help you troubleshoot if you notice problems with your application:
Check the name of the thread from which the fault originates.
If you notice a fault on your Matter device, look at the logs to find the thread that was executing when the error occurred. Sometimes, if there is not enough space in a specific thread, a crash can occur. In such cases, consider increasing the size of the stack dedicated to that thread. Find the thread in the thread and Kconfig option table and change the value of the corresponding Kconfig option in your project configuration.
The code fails on
calloc
/malloc
functions.If your code fails on functions that allocate dynamic memory, try increasing the
CONFIG_CHIP_MALLOC_SYS_HEAP_SIZE
Kconfig value.The code fails while executing some cryptographic operations on an nRF54 Series SoC.
Currently, most cryptographic operations on the nRF54 Series use the current thread’s stack to store operating data. This means that if a demanding cryptographic operation is executed from a thread context with a stack size that is too small, it will cause an unexpected crash. If you notice such an issue, increase the stack size for the failing thread to verify that the cryptographic operations begin to function properly again.