-
-
Notifications
You must be signed in to change notification settings - Fork 958
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FLASH and RAM memory analysis #313
Comments
Can we try reducing the FreeRTOS heap size or is it already at its smallest. We could also try to remake NimBLE but that would require a lot of handwork and isn't guaranteed to succeed. |
I did some quick analysis using a fork of linkermapviz
I uploaded the results of running linkermapviz vs develop: Full and without nimble and lvgl (they take 50% of space by themselves and skew perspective) |
We could try to remake the heavy hitters (The Navigation and AnalogWatchface) from scratch and see if it helps. |
About NimBLE , we could again try replacing parts of it with our own custom made variant or we could try to completely ditch it and make our own stack based on it.(It does seem to use a WHOLE lot of memory) |
it is possible that we are linking the entire static libs while we only use part of them. i spent a while playing with LTO to try and shake the unused bits off, but i did not succeed (managed to get linking working but the resulting file was larger, so probably it both mangled LTO and disabled linker GC pass) |
True , is there anyway to find out which static libs are being used? |
Check the links i posted, the ones ending in `.a` are static
…On Tue, 4 May 2021 at 13:06, MysteriousLog6 ***@***.***> wrote:
it is possible that we are linking the entire static libs while we only
use part of them -- i spent a long while playing with LTO to try and shake
the unused bits off, but it did not work (linking worked but the resulting
bin file was *larger*)
True , is there anyway to find out which static libs are being used?
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#313 (comment)>,
or unsubscribe
</~https://github.com/notifications/unsubscribe-auth/AA33I3TO26S2G5P6LBNMXATTL7WMNANCNFSM43PEJMVQ>
.
--
*Stack* is the new term for "I have no idea what I'm actually using".
|
Absolutely not, I'm very against this. This is not a maintenance burden that's reasonable to take. |
As discussed, incorrect linker/compiler flags or their combinations, but yes it is difficult to achieve correct results. Correct LTO doesn't add size. |
No, that's unlikely to help in any significant way. Just store the used resources on external storage. Code is very very dense and ultra rarely the actual issue (that automated tools can't optimize). |
yea that was implied in my message - now i see it was unclear; sorry for the noise. will update the comment |
Well , is there anyway we can reduce the memory usage of NimBLE? I do understand why your against an entirely new Bluetooth stack , removing parts of it might work. |
Compiling with size optimization ( Another 35-40KB can be moved to flash (fonts + analog clock bg), although adding LittleFS support would bring ~20KB making net gains ~20KB |
So if we move it to the SPI flash we save 30-40 (Let's say 35Kb) and then for LittleFS we have to take another 20kb so about 15Kb. |
Thanks everyone for your work so far! 👍 @MysteriousLog6 I'm don't think that rewriting part or the whole BLE stack would be a good idea. The BLE stack a is very complex piece of code and I doubt we would be able to do better than NimBLE or NRF SoftDevice (the 2 BLE stacks I've worked with so far, and they both need significant amount of flash an ram space). In my opinion, a better way to handle that would be to contribute to NimBLE directly if there are some parts of the code you can improve so that we'll take profit of these optimizations when we upgrade to a more recent version for NimBLE. You've also identified 2 apps (navigation and analog watchface) that use a lot of flash space. Rewriting them probably won't help, as most of the space is taken by graphical assets. As @Avamander said, the most straightforward solution would be to store them in the external flash memory (4MB). Regarding the use of static libraries, I thought that the linker would automatically remove parts of the code that were never used but... we might want to check that! @DavidVentura Thanks for your tools and measurements, I'll definitely have a better look at them as soon as I have some time! It looks like compiling/linking with |
Some, but not all. LTO takes it to a next level, but is not trivial to do correctly. I've mentioned that, somewhere, been a long week.
It just has to be monitored that necessary fast paths are not sacrificed (e.g. display driver speed). |
Linkermapviz is a really great tool, thanks, @DavidVentura ! I modified the script to generate a .csv file of all the symbols from BSS, DATA, RODATA and TEXT sections of the code (on commit 9ab298c). and the resulting csv file: Sections:
-> FLASH usage = TEXT + RODATA + DATA Here are my observations regarding RAM usage:
To be continued:
|
Here another article about Tools for Firmware Code Size Optimization which links to puncover, which looks reaaaaaally interesting! Puncover is really easy to install:
|
Maybe this will help: |
I did a deep analysis of the usage of the buffer dedicated for lvgl (managed by lv_mem). The usage of this buffer can be monitored using this code :
The most interesting metric is I tried to monitor this max value while going through all the apps of InfiniTime 1.1 : the max value I've seen is 5660 bytes. It means that we could probably reduce the size of the buffer from 14KB to 6 - 10 KB (we have to take the fragmentation of the memory into account). |
I also noticed that LVGL allows to specify a custom memory manager instead of the default one implemented in lv_mem. /~https://github.com/JF002/InfiniTime/blob/develop/src/libs/lv_conf.h#L74 |
But would we have to increase the buffer size or remain the same. |
We would probably have to increase the size of the buffer allocated to freertos, but also remove the buffer allocated to lvgl. |
Is the overhead necessary in the future let's say while updating to LVGL 8? So it would be nice to still keep a small overhead to be safe. |
Yes, of course... but a (one) small overhead is better than 2 :) And we will probably have to review the memory allocation as we add features and update components and libraries, this is not written in stone. The issue we are facing right now is that it's really difficult to add anything in the firmware because there's almost no RAM/Flash memory available. |
"Global" stack analysis:This stack will be used for everything except tasks, which have their own stack allocated by FreeRTOS. The stack is 8192B and is allocated in the linker script. Fill the stack section by a known pattern:Edit /modules/nrfx/mdk/gcc_startup_nrf52.S and add the following code after the copy of the data from read only memory to RAM at around line 243:
Dump RAM memory and check usageDumping the content of the ram is easy using JLink debugger and
You can then display the file using objdump:
The stack is positionned at the end of the RAM -> 0xFFFF. Its size is 8192 bytes, so the end of the stack is at 0xE000.
According to my experimentations, we don't use the stack that much, and 8192 bytes is probably way too big for InfiniTime! |
"Global" heap usageThe heap is declared in the linker script and its current size is 8192 bytes. The heap is used for dynamic memory allocation( Heap monitoring is not easy, but it seems that we can use the following code to know the current usage of the heap:
According to my experimentation, InfiniTime uses ~6000bytes of heap most of the time. Except when the Navigation app is launched, where the heap usage increases to... more than 9500 bytes (meaning that the heap overflows and could potentially corrupt the stack!!!). This is a bug that should be fixed in #362. To know exactly what's consuming heap memory, you can
Now, your function Using this technique, I was able to trace all malloc calls at boot (boot -> digital watchface):
Interesting articles : |
About the overflow of stack is this somehow related to #327 , this could probably solve two problems at once. |
@MysteriousLog6
Yes, it could be the cause of the issue, indeed. Any other memory issue could also cause that kind of error, though... |
I summarized this analysis in the following PR : #411 |
`
Hey, I am sorry to respond on a closed thread, but we are working on an embedded system project which utilizes the LVGL library for UI rendering and input handling. Similar to your analysis, I was able to perform memory profiling for objects using the LVGL memory monitors. For our project, it came out around 5KiB during general usage. Therefore, we allocated a However, we are unsure about stack depth caused by the We are looking at revamping our code architecture at this stage, therefore are looking to do some ground work around memory profiling. I stumbled upon your project while I was digging issues on the LVGL repository. PS: We currently don't use any RTOS framework and don't have any plans to integrate it soon. Thanks in advance! Looking forward to your response. |
@kartikCypherock Don't worry, that's fine to respond to this closed thread! Memory management is a complex topic, and that's exactly why I take the time to document all my findings! I'm glad to see that this can be useful to other developers :) FYI I continue this analysis in a new post here and opened a new PR to unify all heaps here. Regarding your question about the stack usage, I wrote this comment about the "global" stack analysis. In this context, I call the Global stack the main stack of the application (as opposed to the stack of the various FreeRTOS tasks that are running in InfiniTime). I can't remember any way to monitor the stack usage at runtime, but you can use those techniques to ensure that your application does not overflow when running specific use-cases. LVGL is integrated in a FreeRTOS task so we can use tools from the OS to get info about the stack usage at runtime : current stack usage and the minimum amount of memory available in the stack since the beginning of the execution. This is very useful to find the best size for all the stacks. |
Now that we've just released version 1.0 of this project, I think it would be useful to take some time to analyze the memory (RAM and FLASH) usage.
Indeed, both memory are nearly full right now : firmware is ~410KB out of the 460KB available, and it's becoming harder and harder to find RAM memory to allocate buffers when needed.
FLASH memory usage should be fairly easy to map using the
.map
file.RAM memory usage is a bit more difficult to figure out. I've already done a bit of researches :
Mapping memory usage will allow us to see what's need to be optimized and which solutions we can implement to be able to continue to add new features and applications.
The text was updated successfully, but these errors were encountered: