Mbed-os: Heap issue in FileSystemStore

Created on 5 Apr 2019  路  14Comments  路  Source: ARMmbed/mbed-os

Description


What target does this relate to?
Nordic Nrf52840
- What toolchain (name + version) are you using?
GCC_ARM , gcc (GCC) 7.4.0
- What tools (name + version - is it mbed-cli, online compiler or IDE) are you using?
mbed cli, also using Visual code studio to debug

Issue is If i am storing a same key and value twice, it is allocating memory twice instead of using the same memory for the defined key and updating the value.
{
mbed_stats_heap_get(&heap_stats);
printf ("Heap1 : Current heap usage: %lu", heap_stats.current_size);
status = _heapBlockDevicefs->set(key_created, value_string, strlen(value_string), 0);
mbed_stats_heap_get(&heap_stats);
printf ("Heap2 : Current heap usage: %lu", heap_stats.current_size);
}
output:
key_created: paper_0 value 0
Heap1 : Current heap usage: 20133
Heap2 : Current heap usage: 21157
key_created: paper_0 value 0
Heap1 : Current heap usage: 21157
Heap2 : Current heap usage: 21669

Issue request type


[ ] Question
[ ] Enhancement
[X ] Bug

CLOSED storage mirrored bug

All 14 comments

Can you please share your code. It's important to understand what file system you're using and how you're defining it. For example, if you're creating LittleFS on a Heap BlockDevice, then your entire Filesystem is on heap, and each operation on a file will inflict in Filesystem overhead level on your heap consumption!
For example FS may create a new second data/metadata node just for updating file content, and still keep the old data for powerfail backup purpose..

//I am using LFS, and heap block device
init()
{
int err;
BlockDevice *bd = new HeapBlockDevice(64 * 512, 512);
// Initialize the block device
LittleFileSystem *fs = new LittleFileSystem("fs", bd);
err = fs->mount(bd);

if (err)
{
    // Reformat if we can't mount the filesystem
    // this should only happen on the first boot
    fflush(stdout);
    err = fs->reformat(bd);
    if (err)
    {
        //error
    }
    else
    {
        _heapBlockDevicefs = new FileSystemStore(fs);
        err = _heapBlockDevicefs->init();
    }
}
else
{
    _heapBlockDevicefs = new FileSystemStore(fs);
    err = _heapBlockDevicefs->init();
}

}

test()
{
mbed_stats_heap_get(&heap_stats);
printf ("Heap1 : Current heap usage: %lu", heap_stats.current_size);
status = _heapBlockDevicefs->set(key_created, value_string, strlen(value_string), 0);
mbed_stats_heap_get(&heap_stats);
printf ("Heap2 : Current heap usage: %lu", heap_stats.current_size);
}
output:
key_created: paper_0 value 0
Heap1 : Current heap usage: 20133
Heap2 : Current heap usage: 21157
key_created: paper_0 value 0
Heap1 : Current heap usage: 21157
Heap2 : Current heap usage: 21669

The updation of metadata, having a copy is fine but for example if i update the value for 10 times it is an overhead of 5k and so on. Finally, i am out of memory, which is not ideal nor my intention.

@AnjanDhumal : as I wrote, you're mounting the entire FS on heap. So, in addition to the file data itself, file system management overhead is inflicting on heap usage. I believe LFS is using double nodes backup logic for its files. I see that the first set added 1 Kbytes of heap and the second set added 512 bytes. Can you please try setting the same value a few more times to see if the heap usage stabilizes or continues to grow in the same delta of 512 bytes. Thanks.

CC: @geky

It just continues to grow un-bounded finally results in using the whole allocated heap memory

@AnjanDhumal - thanks for the info.
@geky , @davidsaada : Can you please review this bug. FileSystemStore opens the file with O_TRUNC flag, which should truncate the file to 0, even if it exists.

https://github.com/ARMmbed/mbed-os/blob/71c84e851f771fbf7d6615e415547d4574009fb0/features/storage/kvstore/filesystemstore/FileSystemStore.cpp#L367

@geky - I think this line will always allocate __prog_size_ buffer, 512bytes per current issue HeapBlockDevice. (unless static lfs->cfg->file_buffer is configured, which I think is not in this case)

https://github.com/ARMmbed/mbed-os/blob/71c84e851f771fbf7d6615e415547d4574009fb0/features/storage/filesystem/littlefs/littlefs/lfs.c#L1369

@geky - pls ignore the previous remark.
upon further analysis, the extra 512bytes are added by calling _lfs_file_sync_() at _lfs_file_close_().
Just before closing the file, _lfs_file_sync_() is writing 512bytes to the BlockDevice which is on Heap, enlarging it by 512bytes each time.

https://github.com/ARMmbed/mbed-os/blob/71c84e851f771fbf7d6615e415547d4574009fb0/features/storage/filesystem/littlefs/littlefs/lfs.c#L1391

@AnjanDhumal - Please note that final analysis shows this is not a real issue.
HeapBlockDevice in your case is constructed of 64 "sectors", each sized 512 bytes.
The overall heap memory this BD will consume is 32Kbyte.
HeapBlockDevice is designed so that each "sector" is allocated only at the first time it is being programmed.
Because LittleFS efficient ware-leveling logic will make use of a different BD "sector" each time, you will end up allocating additional 512 bytes of the HeapBlockDevice per each "set" command. This will continue until you use all of the "sectors" and then previous sectors will be reused.
Try running your program setting the same file more than 64 times, and you'll see that MAX Heap usage will not exceed the HeapBlockDevice 32Kbyte +some constant overhead extra.

Log snippets:
1) For HeapBlockDevice 64*512bytes:
[1555922930.47][CONN][RXD] OFR_DBG Heap 0 : Current heap usage: 5376
[1555922930.47][CONN][RXD] OFR_DBG Heap 1 : Current heap usage: 6400
[1555922930.57][CONN][RXD] OFR_DBG Heap 2 : Current heap usage: 6912
[1555922930.57][CONN][RXD] OFR_DBG Heap 3 : Current heap usage: 7424
.
.
[1555922933.18][CONN][RXD] OFR_DBG Heap 56 : Current heap usage: 34560
[1555922933.18][CONN][RXD] OFR_DBG Heap 57 : Current heap usage: 35072
[1555922933.28][CONN][RXD] OFR_DBG Heap 58 : Current heap usage: 35584
[1555922933.28][CONN][RXD] OFR_DBG Heap 59 : Current heap usage: 35584
[1555922933.38][CONN][RXD] OFR_DBG Heap 60 : Current heap usage: 35584
[1555922933.38][CONN][RXD] OFR_DBG Heap 61 : Current heap usage: 35584

2) For HeapBlockDevice 32*512bytes:
[1555923022.50][CONN][RXD] OFR_DBG Heap 0 : Current heap usage: 5244
[1555923022.50][CONN][RXD] OFR_DBG Heap 1 : Current heap usage: 6268
[1555923022.60][CONN][RXD] OFR_DBG Heap 2 : Current heap usage: 6780
[1555923022.60][CONN][RXD] OFR_DBG Heap 3 : Current heap usage: 7292
.
.
[1555923023.60][CONN][RXD] OFR_DBG Heap 24 : Current heap usage: 18044
[1555923023.70][CONN][RXD] OFR_DBG Heap 25 : Current heap usage: 18556
[1555923023.70][CONN][RXD] OFR_DBG Heap 26 : Current heap usage: 19068
[1555923023.81][CONN][RXD] OFR_DBG Heap 27 : Current heap usage: 19068
[1555923023.81][CONN][RXD] OFR_DBG Heap 28 : Current heap usage: 19068

3) For SPIFBlockDevice (Block device does not use heap) :
[1555923849.51][CONN][RXD] OFR_DBG Heap 0 : Current heap usage: 1856
[1555923849.66][CONN][RXD] OFR_DBG Heap 1 : Current heap usage: 1856
[1555923849.77][CONN][RXD] OFR_DBG Heap 2 : Current heap usage: 1856
[1555923849.87][CONN][RXD] OFR_DBG Heap 3 : Current heap usage: 1856
[1555923849.97][CONN][RXD] OFR_DBG Heap 4 : Current heap usage: 1856
[1555923850.17][CONN][RXD] OFR_DBG Heap 5 : Current heap usage: 1856
.
.

@AnjanDhumal - please let me know if the issue can be marked resolved.
Thanks

@0xc0170 - can you please close this as "not a bug" - thanks.

@AnjanDhumal - please let me know if the issue can be marked resolved.
Thanks

Agree, it can be marked resolved and closed. thank you.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

bcostm picture bcostm  路  4Comments

ccchang12 picture ccchang12  路  4Comments

cesarvandevelde picture cesarvandevelde  路  4Comments

toyowata picture toyowata  路  4Comments

DuyTrandeLion picture DuyTrandeLion  路  3Comments