locoduino / memoryusage Goto Github PK
View Code? Open in Web Editor NEWThis is a library for Arduino to see memory usage during a program execution.
Home Page: http://www.locoduino.org
License: GNU General Public License v2.0
This is a library for Arduino to see memory usage during a program execution.
Home Page: http://www.locoduino.org
License: GNU General Public License v2.0
Hi. Thank you for publishing this library. I wanted to make something similar, but it was good to see you had a library already available!
Unfortunately, I have not been able to get MemoryUsage to report any changing values for the example sketches (or for my own sketches). I expected the examples to report changing values as storage was allocated and released. Am I using the library incorrectly?
My environment:
I tried to run the example sketches "FreeRam" and "Stack".
NOTE 1:
The MemoryUsage examples are under File/Examples/INCOMPATIBLE/MemoryUsage...
The examples seemed to compile anyway.
NOTE 2: Stack.ino
Stack.ino builds with the following warning:
WARNING: library MemoryUsage claims to run on AVR architecture(s) and may be incompatible with your current board which runs on avr architecture(s).
C:\Users\philk\OneDrive\Documents\Arduino\libraries\MemoryUsage\src\MemoryUsage.cpp: In function 'uint16_t mu_StackCount()':
C:\Users\philk\OneDrive\Documents\Arduino\libraries\MemoryUsage\src\MemoryUsage.cpp:76:39: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
while (*p == STACK_CANARY && (int) p <= SP)
^
Sketch uses 5262 bytes (16%) of program storage space. Maximum is 32256 bytes.
Global variables use 286 bytes (13%) of dynamic memory, leaving 1762 bytes for local variables. Maximum is 2048 bytes.
The sketch output gives values that never change. For example stack size is always 1256 bytes:
Starting state of the memory:
Data start:256
Heap start:542
Heap end:542
Stack start:1047
Stack end:2303
Stack size:1256
Stack Maximum Size (Painting method): 1761
subPointer
Test string
Stack start:1047
Stack end:2303
Stack size:1256
Stack Maximum Size (Instrumentation method): 1256
subSmartPointer
Test string
Stack start:1047
Stack end:2303
Stack size:1256
Stack Maximum Size (Instrumentation method): 1256
subConstSmartPointer
Test string
Stack start:1047
Stack end:2303
Stack size:1256
Stack Maximum Size (Instrumentation method): 1256
subFull
Test string
Stack start:1047
Stack end:2303
Stack size:1256
Stack Maximum Size (Instrumentation method): 1256
subLocalData
10.00
Stack start:1047
Stack end:2303
Stack size:1256
Stack Maximum Size (Instrumentation method): 1256
Stack Maximum Size (Painting method): 1761
Ending state of the memory:
Data start:256
Heap start:542
Heap end:542
Stack start:1047
Stack end:2303
Stack size:1256
These values were supposed to change (at least temporarily), correct?
NOTE 3: FreeRam.ino
FreeRam.ino builds with the following warning:
WARNING: library MemoryUsage claims to run on AVR architecture(s) and may be incompatible with your current board which runs on avr architecture(s).
C:\Users\philk\OneDrive\Documents\Arduino\libraries\MemoryUsage\examples\FreeRam\FreeRam.ino: In function 'void setup()':
C:\Users\philk\OneDrive\Documents\Arduino\libraries\MemoryUsage\examples\FreeRam\FreeRam.ino:21:11: warning: unused variable 'p' [-Wunused-variable]
byte *p = new byte[3000];
^
C:\Users\philk\OneDrive\Documents\Arduino\libraries\MemoryUsage\src\MemoryUsage.cpp: In function 'uint16_t mu_StackCount()':
C:\Users\philk\OneDrive\Documents\Arduino\libraries\MemoryUsage\src\MemoryUsage.cpp:76:39: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
while (*p == STACK_CANARY && (int) p <= SP)
^
Sketch uses 2458 bytes (7%) of program storage space. Maximum is 32256 bytes.
Global variables use 192 bytes (9%) of dynamic memory, leaving 1856 bytes for local variables. Maximum is 2048 bytes.
The sketch output gives values that never change. For example the free RAM size is always 1850 bytes:
Starting state of the memory:
Data start:256
Heap start:448
Heap end:448
Stack start:2297
Stack end:2303
Heap size:0
Free Ram Size: 1850
Ending state of the memory:
Data start:256
Heap start:448
Heap end:448
Stack start:2297
Stack end:2303
Heap size:0
Free Ram Size: 1850
Again, these values were supposed to change (at least temporarily), correct?
+----------------+ 256 (__data_start)
+ data +
+ variables + size = 264
+----------------+ 520 (__data_end / __bss_start)
+ bss +
+ variables + size = 673
+----------------+ 1193 (__bss_end / __heap_start)
+ heap + size = 0
+----------------+ 1193 (__brkval if not 0, or __heap_start)
+ +
+ +
+ FREE RAM + size = -15
+ +
+ +
+----------------+ 2801 (SP)
+ stack + size = 15
+----------------+ 2815 (RAMEND / __stack)
FREE RAM size does not display the free ram size, it displays the negative stack size.
(I am pulling out this comment from #3 as its own topic as I think it will be helpful.)
After compiler optimization many expected side effects can disappear:
This is all good in principle. But the optimizations make it difficult to predict how much stack space is needed, just by inspection. Even for a simple example. Often nothing seems to change, especially for simple examples.
I was able to get more predictable results by:
noinline
, for example void __attribute__ ((noinline)) myStackUsingFunction(void) {...};
. This ensures the function call will exercise the stack so this library can observe it.volatile
, which hints to the compiler it should manipulate the variable (and put it on the stack), even if it seems unnecessary.Note that noinline
and volatile
declarations make memory usage more predictable, but less efficient. It may be useful while you are still debugging your code. Once you are done debugging your memory allocations, you might want to take the declarations out so the optimizers can help free up RAM storage.
This is for an Arduino Uno, which has only 2048 bytes RAM available.
The problem is really in examples/FreeRam/FreeRam.ino, but its output is harder to interpret.
The actual issue is on FreeRam.ino line 21:
...
byte *p = new byte[3000];
...
Since there is only 2k RAM available this allocation will fail on an Uno. On failure, nothing gets allocated on the heap, and the heap size does not change. This is not not so interesting for an example.
I found a smaller array size made FreeRam.ino more interesting:
...
byte *p = new byte[300];
...
See #4 for a pull request to make this allocation request successful.
For a more direct demonstration the heap growing and shrinking, I wrote GetMemorySize.ino:
#include <MemoryUsage.h>
// Simple example to report memory sizes
void reportAllocation(int numBytes) {
Serial.print(F("Allocating for "));
Serial.print( numBytes );
Serial.print(F(" bytes; "));
byte *p = new byte[numBytes];
if (p) {
Serial.println(F("...success."));
} else {
Serial.println(F("...allocation FAILED"));
}
MEMORY_PRINT_HEAPSIZE
FREERAM_PRINT
Serial.println(F("\ndeleting byte array with delete"));
delete p; // don't want a memory leak!
p = 0; // don't want a dangling/obsolete pointer
MEMORY_PRINT_HEAPSIZE
FREERAM_PRINT
}
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println(F( "Running " __FILE__ ", Built " __DATE__));
Serial.println(F("\nStarting conditions"));
MEMORY_PRINT_TOTALSIZE
MEMORY_PRINT_HEAPSIZE
FREERAM_PRINT
Serial.println(F("\nallocate a byte array with new; too big to fit in RAM?"));
reportAllocation(3000);
Serial.println(F("\nallocate smaller byte array with new (it should fit)"));
reportAllocation(300);
Serial.println(F("\nFinal conditions"));
MEMORY_PRINT_HEAPSIZE
FREERAM_PRINT
}
void loop() {
// User reads output from setup().
}
This is for an Arduino UNO, which has 2048 bytes of total RAM.
Run the following sketch "GetMemoryTotalSize.ino":
#include <MemoryUsage.h>
// Simple example to report memory TOTAL size
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println(F( "Running " __FILE__ ", Built " __DATE__));
Serial.println();
MEMORY_PRINT_TOTALSIZE
}
void loop() {
// User reads output from setup().
}
Your serial monitor generates an output something like this:
Running C:\Users\philk\OneDrive\Documents\Arduino\GetMemoryTotalSize\GetMemoryTotalSize.ino, Built Jun 4 2021
SRAM size:2047
NOTE: The RAM size reported is 2047 bytes (not 2048 bytes).
This is because the END
macro returns the address of the last byte of RAM (not the byte after it). So beginning and end are inclusive limits.
It is harder to recognize problem because the start of RAM is at 0x100, so it's harder to tell where 2k byte RAM boundaries should really belong (particularly as decimal numbers).
See #4 for a fix.
The routine mu_StackPaint is not executed in section .init1
I use platformio and board = 1284p16m
better results with this approach:
https://www.avrfreaks.net/comment/1314296#comment-1314296
with little modification to take in account heap:
extern uint8_t _end;
void simpleStackPaint(void)
{
uint8_t *p = &_end;
while(p < (uint8_t*)&p)
{
*p = 0xc5;
p++;
}
}
uint16_t simpleStackCount(void)
{
const uint8_t *p = (int) (__brkval == 0 ? (uint8_t *) &__heap_start : __brkval);
//const uint8_t *p = &_end;
uint16_t c = 0;
while(*p == 0xc5 && p < (uint8_t*)&p)
{
p++;
c++;
}
return c;
}
The MemoryUsage macros provide good insight into what is happening with RAM storage.
But it would be nice to have the library return numeric values, too. This could be used in different ways:
I have created a pull request #7 which could help with this suggestion. Please let me know if you have questions or concerns.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.