How to know how much RAM/Flash i am using

When using the web IDE it would be great when we compile for it to show how much ram & flash the app we created is using up. right now i have no idea how close to the wall i am.

1 Like

Hi @seulater

Good idea! I’m adding this to our feature backlog, and we’ll try to post here if it gets added.

Thanks!
David

I’ve been wanting to do this, so thanks for the push! Read the comments near the bottom… seem legit?

Adapted from:
http://playground.arduino.cc/Code/AvailableMemory

    unsigned int __heap_start;
    void *__brkval;
    
    /*
     * The free list structure as maintained by the 
     * avr-libc memory allocation routines.
     */
    struct __freelist {
      size_t sz;
      struct __freelist *nx;
    };
    
    /* The head of the free list structure */
    struct __freelist *__flp;
    
    // MemoryFree library based on code posted here:
    // http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1213583720/15
    // 
    // Extended by Matthew Murdoch to include walking of the free list.
    
    //#ifdef __cplusplus
        //extern "C" {
    //#endif
    
    int freeMemory();
    
    //#ifdef __cplusplus
        //}
    //#endif
    
    /* Calculates the size of the free list */
    int freeListSize() {
      struct __freelist* current;
      int total = 0;
    
      for (current = __flp; current; current = current->nx) {
        total += 2; /* Add two bytes for the memory block's header  */
        total += (int) current->sz;
      }
    
      return total;
    }
    
    int freeMemory() {
      int free_memory;
    
      if ((int)__brkval == 0) {
        free_memory = ((int)&free_memory) - ((int)&__heap_start);
      } else {
        free_memory = ((int)&free_memory) - ((int)__brkval);
        free_memory += freeListSize();
      }
      return free_memory;
    }
    
    // On Spark Core
    //
    // Reported free memory with str commented out:
    // 17584 bytes RAM
    //
    // Reported free memory with str and Serial.println(str) uncommented:
    // 17552 bytes RAM
    //
    // Difference: 32 bytes (31 ascii chars + null terminator)
    
    // 14-bytes string
    //char str[] = "Hello, Spark!!! Hello, Spark!!!";
    
    void setup() {
        Serial1.begin(115200);
    }
    
    
    void loop() {
        //Serial1.println(str);
    
        Serial1.print("freeMemory()=");
        Serial1.println(freeMemory());
    
        delay(1000);
    }
2 Likes

Thats a start, but it would be better if the web IDE showed that when it compiles it.

Nice freememory function!

I love the idea of adding this as a compile step, I’m guessing I’d just run something like…

arm-none-eabi-size user-firmware.elf

and include some kind of output like:

   text	   data	    bss	    dec	    hex	filename
  65292	   2912	  11532	  79736	  13778	user-firmware.elf

Yeah? I could add that as a compiler step, but it might take a while before the web ide is updated to show it – gotta check with those guys. Adding it to my list! :smile: (We are really keeping track of all this stuff)

Thanks,
David

2 Likes

What would be useful to know is the xxx,xxx bytes used / xxx,xxxx bytes free for FLASH and RAM :wink:

Is there a way to get that info from the .elf? If so we should update the makefile to include it!

2 Likes

What about free Flash size Or flash used. I need to know how close to the wall i am with my code.

1 Like

I’ve tested this function and looks great. I 'm having some trouble with ram because I easily run out of it . I used this function to do some tests… and I get strange results.

The program only consists on the freememory() function and this struct:

typedef struct{
    uint8_t po;
    String co;
    String na;
    uint8_t re;
    uint32_t lo;
} Ndata;

Ndata matrixA[MATRIX_SIZE];

If MATRIX_SIZE is 20, I’ve got 17064 bytes RAM. Or if MATRIX_SIZE is 30, I’ve got 16624 bytes RAM.
BUT if MATRIX_SIZE is 40, cores starts blinking red (8 times -> run out of space).

Don’t I have enought memory? What is happening? I’m new to all of this so your help would be very useful!
Thanks guys.

When matrixA is declared public, that really is odd.
But as a wild guess, looking at the implementation of the String class - of which you use two per instance of Ndata - and if you have matrixA declared as local var you might not run out of “User RAM” but out of stack space (Stack Overflow).

On the other hand I believe having read in another thread that the available RAM - once the Spark stuff has taken its share - is only about 6K and no 16K.
But this might have changed since then.

clex, the Spark has about 6KB of available user RAM. That RAM is then allocated to the heap and the stack. Based on your results, each array entry takes 44 bytes of code which seems odd with those two String variables in there. You could print the sizeof(Ndata) to give you an idea of the structure size. I have to look at the the default String size allocation is as well.

I have just put this little sketch together to look how String behaves in memory

char x = 0;
String s1;
char y = 0;

void setup()
{
	Serial.begin(115200);
}

void loop()
{
	char z = 0;
	String s2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";

	Serial.print("global x  @ 0x");
	Serial.println((unsigned long)&x, HEX);

	Serial.print("global s1 @ 0x");
	Serial.print((unsigned long)&s1, HEX);
	Serial.print(" sizeof(s1) ");
	Serial.print(sizeof(s1), DEC);
	Serial.print(" s1.buffer @ 0x");
	Serial.print((unsigned long)(s1.buffer), HEX);
	Serial.print(" allocated buffer ");
	Serial.println(s1.capacity + 1, DEC);

	Serial.print("global y  @ 0x");
	Serial.println((unsigned long)&y, HEX);

	Serial.print("local  z  @ 0x");
	Serial.println((unsigned long)&z, HEX);

	Serial.print("local  s2 @ 0x");
	Serial.print((unsigned long)&s2, HEX);
	Serial.print(" sizeof(s2) ");
	Serial.print(sizeof(s2), DEC);
	Serial.print(" s2.buffer @ 0x");
	Serial.print((unsigned long)(s2.buffer), HEX);
	Serial.print(" allocated buffer ");
	Serial.println(s2.capacity + 1, DEC);

	Serial.println("");

	delay(1000);
}

This produced this output:

global x  @ 0x200009C4
global s1 @ 0x200009C8 sizeof(s1) 16 s1.buffer @ 0x20002358 allocated buffer 1
global y  @ 0x200009D8
local  z  @ 0x20004FCF
local  s2 @ 0x20004FD0 sizeof(s2) 16 s2.buffer @ 0x20002368 allocated buffer 37

So it seems that each String instance consumes 16 byte for itself plus some memory to hold the actual string on the heap (via realloc). And as it seems although s1 is an empty string (+ \0) realloc for s2 places its buffer 16 byte further on (0x20002358 vs. 0x20002368).

Furthermore
the first global user var x is placed at 0x200009C4 (“global/user” section)
the first user heap object s1.buffer is placed at 0x20002358 (heap section) and
the first local user var z is placed at 0x20004FCF (stack section)


One other interesting thing to be noticed is the placement of s1 relative to x.
Although x should only occupy one byte in RAM it seems to take up four (0x9C4 - 0x9C7).
But in fact it does not. As @psb777 found out in this thread it actually only does use one single byte in RAM - for itself that is!
The “wasted” three byte here are caused by s1 - or more correctly s1.buffer, the first field of String class to be allocated in RAM.
Since this is declared as char *buffer it is a pointer and as such a four byte entity which demands to be placed on a four byte boundary, hence causing the three byte gap between x and s1.
This might also be the reason why @peekay123 sees 44 (= 1 (+3) + 16 + 16 + 1 (+3) + 4) bytes instead of 38 which you would expect once you add up the the datatype sizeof() (1 + 16 + 16 + 1 +4).
So to save some space you could rearrange your uint8_t to be placed adjacent wich would result in (1 + 1 (+2) + 16 + 16 + 4) 40 bytes.

3 Likes

Thanks!! Now I understand better what was happening. @ScruffR thanks for you analysis, very useful!

1 Like

Hey :spark: community,

As you know the :spark: Team and Elites are committed to doing our best and make :spark: core awesome…

This is a new feature in the Web IDE which should already be available to everyone!

Displaying Ram Usage when verifying

*Right now, you need to modify the code each time before you verify. Something like adding a SPACE works too.

It’s a hard backend issue to display it every time but we are looking into it!


Special thanks to:

@bko for the script to extract the information,
@jgoggins for pushing this feature fast,
@Dave for changing the backend and
@shime who did the IDE changes!

Not forgetting everyone in the :spark: Elite who came up with this idea and made it happen in a short span of 16 Days (minus 5 days for Maker Faire)

Some applause from the audience? :smiley:

3 Likes

Hi BDub,

Is there any way to use this in order to determine the amount of RAM available at any point in the application? I would like to print out the amount of User RAM available since I seem to be getting RED LED message out of heap memory to help tell where I am running out of RAM in my application.

See this thread for why it is hard:

Summary--you have to walk the linked list created by malloc to know how much heap is in use.

Can this script be applied to local build environments as well? Not everybody uses the Web IDE, and the Dev IDE doesn't have this feature.

@WebDust21, on the latest develop branch:

System.freeMemory() API to determine the amount of available RAM.

:smile:

@peekay123: Woohoo! I’ll have to give it a shot!
I figured that if the system knew how to give an out-of-memory SOS, there was a way to know how much memory was available! I suppose that I can live with the weird startup LED patterns in MANUAL mode…and reliability seems to be about the same as LATEST, RELEASE 0.4.3, Particle Dev IDE, etc.

Been away from this platform for a very long while. Got a new project that I thought would benefit from it. In checking it out I still don’t see a way from my OP that this has feature has been added. Is this true ?
I think its very important to know just how much code space is left while developing.