Buffer Manager¶
Overview¶
The buffer manager is a new feature added to framework version 1.6.0. This feature unifies storage of framework subsystems in order to more easily manage RAM and flash.
Buffers are 4096 bytes (4kB) in length. Buffers are grouped into buffer pools, with one pool assigned to each system that needs to buffer data. For example, the RPC output buffer and each ZCL reporting group (see Reporting) are assigned their own buffer pool. Each buffer pool is always guaranteed two RAM buffers; beyond that, the total available RAM and flash buffers are divided between buffer pools based on their priority. Note that until memory is depleted, any buffer pool may freely obtain additional buffers. Buffer pool priority is only significant when there is no space and some data must be dropped, at which point pools with higher priority will get relatively more of the available memory.
The buffer manager by default will attempt to keep data power safe. It does this by moving the pool’s buffers into flash after some configurable length of time where the buffer pool is not empty (Registry Settings under “Buffer_Manager.store_to_flash_delay”).
Priority¶
Each buffer pool has an associated priority that guarantees a certain amount of RAM and flash for its use. Priorities are relative and based on configuration of the whole system. The Buffer Manager takes the following steps to calculate how much RAM and flash to guarantee to each buffer pool.
- Get total available RAM and flash for the system from Registry Settings using Buffer_Manager.max_ram_size and Buffer_Manager.max_flash_size.
- Split total RAM and flash into buffers of 4096 bytes (4kB).
- Subtract 2 RAM buffers for every buffer pool from the total RAM (these are always guaranteed at a minimum) and assign this as the adjusted total RAM.
- Add up the priority of all of the buffer pools to get a total priority for the system. Note that buffer pools default to a priority of zero.
- If the total priority is zero, the buffer pools split the buffers evenly.
- Calculate the guaranteed RAM of each buffer pool: guaranteed RAM = 2 + (adjusted total RAM * priority / total priority).
- Any leftover RAM is added to the highest priority buffer pool.
- Calculate the guaranteed flash of each buffer pool: guaranteed flash = total flash * priority / total priority.
- Any leftover flash is added to the highest priority buffer pool.
- This calculation is run:
- After the Buffer Manager initializes all of it buffer pools
- When a buffer pool is added or removed
- When the total available RAM or flash changes
Buffer Management¶
Each buffer pool will try to keep its data in RAM for fast access and in flash to prevent data loss on reset. This is not always practical or possible because of the slowness of writing to flash, worries about flash wearing, and resource limits. The Buffer Manager tries to balance these requirements to achieve the best possible performance without losing data during resets.
All buffer pools initially store data in a RAM buffer.
RAM | Flash | ||||||||
1 |
Buffers are added to RAM on an as-needed basis (as long as there are free RAM buffers available).
RAM | Flash | ||||||||
1 | 2 |
If more than Registry Settings “Buffer_Manager.store_to_flash_delay” seconds have elapsed and the buffer hasn’t been emptied, the data is mirrored in flash. The delay is implemented to prevent the system from wearing out the flash from too many flash writes. Also flash writes are relatively slow and unneeded if the data is processed out the buffer pool quickly. Any data appended to a buffer will be appended to both RAM and flash.
RAM | Flash | ||||||||
1 | 2 | 1 | 2 |
Buffers are added to RAM and flash on an as-needed basis (as long as there are free RAM and flash buffers available).
RAM | Flash | ||||||||
1 | 2 | 3 | 1 | 2 | 3 |
Things start to get interesting when there are no longer any RAM or flash buffers available. If a buffer pool needs another RAM or flash buffer and it is guaranteed another space, it will take one of the excess buffers from another buffer pool. There will always be an available buffer, since the total size of guaranteed RAM and flash buffers does not exceed the total size of the available RAM and flash. If a buffer pool can no longer store data in both RAM and flash, it may start to store the newer data is flash and the older data in RAM. This allows the older data to be quickly sent from RAM and saves the newer data against loss on a reset. If there is no more flash available for new data, data that is currently in flash will get moved to RAM and the new data will be added to the flash.
Let’s assume that our buffer pool has 3 guaranteed RAM buffers and 2 guaranteed flash buffers. If there were no free RAM or flash buffers available and another buffer pool needed a flash buffer, the buffer pool would drop buffer 1 from flash. Note that some of the buffers are still being mirrored in both RAM and flash.
RAM (3) | Flash (2) | ||||||||
1 | 2 | 3 | 2 | 3 |
If there were no free RAM or flash buffers available and a 4th buffer was needed, the buffer pool would drop the 2nd flash buffer. Note that buffer 3 is still being mirrored in both RAM and flash.
RAM (3) | Flash (2) | ||||||||
1 | 2 | 3 | 3 | 4 |
If there were no free RAM or flash buffers available and a 5th buffer was needed, the buffer pool would drop the 3rd flash buffer. Note that buffers are not longer being mirrored.
RAM (3) | Flash (2) | ||||||||
1 | 2 | 3 | 4 | 5 |
If there were no free RAM or flash buffers available and a 6th buffer was needed, the buffer pool would drop the 1st buffer completely, move the 4th buffer from flash to RAM, and add the 6th buffer to flash.
RAM (3) | Flash (2) | ||||||||
2 | 3 | 4 | 5 | 6 |
If RAM became available but flash was not available and a 7th buffer was needed, the buffer pool would move the 5th buffer pool to RAM and add a 7th buffer to flash.
RAM (3) | Flash (2) | ||||||||
2 | 3 | 4 | 5 | 6 | 7 |
If flash became available and an 8th buffer was needed, the buffer pool would add the 8th buffer to flash.
RAM (3) | Flash (2) | ||||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
If another buffer pool needed to steal a RAM buffer from this buffer pool, this buffer pool would drop the 2nd buffer pool.
RAM (3) | Flash (2) | ||||||||
3 | 4 | 5 | 6 | 7 | 8 |
If there is no free RAM or flash and another buffer pool needed to steal a flash buffer from this buffer pool, this buffer pool would drop buffer 3 and move buffer 6 from flash to RAM.
RAM (3) | Flash (2) | ||||||||
4 | 5 | 6 | 7 | 8 |