Memory Usage Report Only Works for Globals?

Go To Last Post
25 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've noticed that when I compile my code with GCC and view the memory usage report at the bottom, it only seems to reflect global variables. I can introduce a local variable: float temp[500]; and recompile and the memory usage doesn't change at all unless I decide to make that global. I've noticed this a long time ago, and actually got into the habit of making almost all my variables global just so I could know my memory usage. Is there any other way to go about this?

Thanks,
James

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jdowns wrote:
I've noticed that when I compile my code with GCC and view the memory usage report at the bottom, it only seems to reflect global variables.
Actually, it's not just global variables but statically allocated variables whether they're local to a function, local to a module or global in scope.

jdowns wrote:
I can introduce a local variable: float temp[500]; and recompile and the memory usage doesn't change at all[...]
Of course not. That space is dynamically allocated. The compiler could list the amount of local stack space consumed by each function. (That would, of course, require processor-specific code.) It could also (in most cases) perform a static analysis of the maximum stack depth that will occur beginning from main() and taking into account the ISRs that are present. I said "in most cases" because recursion and indirect calls are problematic and may render static analysis meaningless or impossible.

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

Last Edited: Sat. Nov 8, 2008 - 08:31 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay, thanks... I didn't know that was how it worked.

Regards,
James

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jdowns wrote:
Is there any other way to go about this?

I'm also looking for ways to get memory usage report that includes the local variables. So far the only solution I came up with is to write my own utility that does that. There is a little bit more about that at the end of the following thread:
https://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=70059

What is strange to me is that there does not seem to be much interest in a tool like that.

Eugene

EDIT: fixed the link.

Last Edited: Sun. Nov 9, 2008 - 08:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, it's strange to me too... I have resorted to making almost all of my variables global just to know what my memory usage is.

James

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jdowns wrote:
I have resorted to making almost all of my variables global just to know what my memory usage is.
That seems to be an overreaction and it is likely to be counterproductive.

You can determine your stack use empirically at run-time by adding a small amount of diagnostic code to your application. Step 1 is to seed the stack area with a known value, e.g. 0x55. This has to be done early in the your initialization code. Step 2 is to exercise your application thoroughly, with an eye toward ensuring that all executions paths are followed. Step 3 is to examine the stack area to find the lowest addressed byte that is not the seed value. That address can then be compared to the highest statically allocated RAM address (from the .sym file), the difference is the amount of unused stack space.

This topic and this technique have been discussed here several times.

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ezharkov wrote:
So far the only solution I came up with is to write my own utility that does that.
I believe that it would be very difficult to implement a generalized tool that could statically analyze stack use for an arbitrary AVR application.

There is some discussion of the static analysis tool for our ZBasic compiler (that uses avr-gcc as a back-end compiler) near the end of the thread at https://www.avrfreaks.net/index.p.... This is a more specific use case but some of the ideas could be employed for a general avr-gcc application.

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Eugene!

The link you supplied to some other thread here is broken. Even if I fix ".ne" to ".net" it eads to a server error. What thread is it that you are talking about?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Tell me the consumption of RAM that will come from the factorial function in the sketchy code below..

#include 

int factorial(int n)
{
   int temp;

   if (n==0) {
      temp = 1;
   }
   else {
      temp = factorial( n - 1 ) * n;
   }
   return temp;
}

int main(void)
{
   DDRD = 0xFF;
   PORTD = factorial(PINB);
   while (1);
   return 0;
}

And for the sake of this demonstration, of the difficulties constructing a general tool for calculating at build time the memory consumption at run time, please assume that the compiler is run with no optimization.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dkinzer wrote:
There is some discussion of the static analysis tool for our ZBasic compiler (that uses avr-gcc as a back-end compiler) near the end of the thread at https://www.avrfreaks.net/index.p.... This is a more specific use case but some of the ideas could be employed for a general avr-gcc application.

I'm not familiar with your product. So, what do you do? Do you translate Basic into C, then use gcc to compile to binary AVR code, right? You say that you are "analyzing the AVR machine code produced by the linker". Have you instead considered adding stack size options to the gcc itself? Is that really difficult? Even for simple applications without indirect calls and recursions? I have not looked into gcc code myself, so I really have no idea. But, for example, in the other thread I posted a link where some guys seem to suggest that it is doable. Here is that link again:
http://www.adacore.com/wp-content/uploads/2005/06/Stack_Analysis.pdf

Eugene

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
Eugene!

The link you supplied to some other thread here is broken. Even if I fix ".ne" to ".net" it eads to a server error. What thread is it that you are talking about?


Well, let's try one more time:
https://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=70059

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ezharkov wrote:
Do you translate Basic into C, then use gcc to compile to binary AVR code, right?
That is correct.
ezharkov wrote:
Have you instead considered adding stack size options to the gcc itself? Is that really difficult?
I didn't consider this option because I didn't want to have to use a custom version of the compiler.
ezharkov wrote:
I posted a link where some guys seem to suggest that it is doable.
I hadn't seen that paper but they cover all of the issues that I encountered when I studied the problem and implemented the analyzer using object code examination. There are several difficult issues to handle including recognition of the several idioms used by the compiler to allocate and deallocate from the stack, save/restore registers, etc.

As noted (and as should be obvious) recursion, whether direct or indirect is an intractable problem lacking user guidance. The indirect calls problem can be mitigated with user guidance as well.

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
Tell me the consumption of RAM that will come from the factorial function in the sketchy code below..
Well, I tried to answer a similar question in that other thread, with the incorrect link. My answer was along the lines that, yes, it is impossible to create a generic tool that works in 100% of the cases. Does that mean that we should not even think about a tool that works in 90% of the cases and gives an appropriate warning in the other 10% cases?

Eugene

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Surely anyone writing embedded software will be doing a "memory budget" to decide which device is most appropriate/cost effective for the required solution and you'll do a "back of the envelope" dynamic analysis (statically!) by hand anyway?

The real easy asnwer IS to make everything global or at least static in fact. But I guess the "purists" don't like this as it contradicts everything they were taught in "Computing 101"?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
The real easy asnwer IS to make everything global or at least static in fact.
In addition to being wasteful of a relatively scarce resource, that strategy doesn't really solve the problem. You'll still have an unknown amount of RAM needed for subroutine invocation and for interrupt service routines. One could argue, I suppose, that that simplifies the problem enough that you can determine the missing information by inspection of the object code.

On the other hand, you could choose not to use interrupts and to have your entire application in main() with no subroutine calls. In that case, making everything statically allocated does solve the problem.

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

dkinzer wrote:
In addition to being wasteful of a relatively scarce resource, that strategy doesn't really solve the problem.

Sorry but I don't agree. I mean how many of your automatics are really just a locally used i,j,k loop counter or a general purpose uint8_t buffer[20] or something? So keep one set of i/j/k and a general_purpose_reusable_buffer[40] or whatever and just use the hell out of them.

As for then worrying about dynamic usage. Surely you'll have an idea of your deepest stack nesting and the worst case for an ISR would be if it stacked 32 bytes for ALL the registers.

(or are people REALLY mad enough to use recursion in an embedded program or allow for interruptible ISRs?!?)

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

(or are people REALLY mad enough to use recursion in an embedded program?!?)

Well, I hope you know that I was rethorical..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Well, I hope you know that I was rethorical..

Indeed! I was going to point out that I realised you were clearly just making a point about the impossibility of dynamic analysis (the last time Dr Zharkov started a thread about this I qouted the very same example (factorial) in fact!). But I guessed that both you and I knew the motive behind your post. ;)

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Sorry but I don't agree. I mean how many of your automatics are really just a locally used i,j,k loop counter or a general purpose uint8_t buffer[20] or something? So keep one set of i/j/k and a general_purpose_reusable_buffer[40] or whatever and just use the hell out of them.

Oh, come on. I'm not a purist. My buffers are usually global. But making i/j/k global? Don't you think this is a bit extreme? I have done a bit of that on PIC16. Because there is no other choice there. But to make your application intentionally unreadable and unmaintainable on a C-friendly AVR architecture?

Eugene

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

But I guessed that [..] you [...] knew the motive behind your post.

LOL! Note to self: When shooting at Clawson - prepare for the recoil..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

But making i/j/k global? Don't you think this is a bit extreme?

Agree with Eugene here. Now were back at the dark ages where two functions use the same global variables. Works fine until one calls the other. In my world, avoiding these kind of problems is the ultimate reason for locals / automatics. In mebedded you have to compromize as you don't want to allocate huge structures on the stack. But saving a few bytes for index/loop-control variables...?

[preparing for the recoil...]

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well... I'm just glad to know I'm not the only one who programs that way... i.e. globals everywhere including things like i,j,k and one re-usable char buffer array, etc... I do exactly that in my code...

James

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ezharkov wrote:

What is strange to me is that there does not seem to be much interest in a tool like that.

There is actually a lot of interest. It just happens to be a very difficult problem.

Search the web for 'stacktool' by John Regehr. He is a Computer Science professor at the University of Utah, which I happened to be acquainted with for several years now.

A few years back he created such a tool for the AVR, for a research paper, which got publish in Embedded Systems Programming (now Embedded Systems Design) magazine. I'm sure you look it up at the magazine's website: www.embedded.com.

This is a very difficult problem to solve, and unfortunately, Dr. Regehr's 'stacktool' program did not work for me on some real-world, large AVR applications. But the code is open source, IIRC.

I have told him (several times) that I would love for the 'stacktool' program to fixed so I could include it in WinAVR.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

EW wrote:
Search the web for 'stacktool' by John Regehr
I did. Actually you pointed me to stacktool, in another thread. It did not work for me either and I ended up writing my own. It looks that my tool is going to work for me. But I still would have preferred if there was a solution at the compilation level.

BTW, if anyone interested, here is my tool: http://home.comcast.net/~ezstack/ezstack.c

It is kind of messy at this point. It does not support recursions, indirect calls, alloca, long switches. It assumes that interrupts are not re-enabled in the middle of interrupt routines. Most likely it does not support many other things.

I compile it using windows's cl.exe. But I think it should work pretty much everywhere else (well, little endian only). There are no command line options at this point. Just "ezstack file.elf".

Eugene

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ezharkov wrote:
BTW, if anyone interested, here is my tool
Very interesting. The approach is essentially the same as mine, i.e., implementing an AVR simulator/interpreter to track register content and producing call graphs by analyzing execution flow. Instead of processing the .elf file, I analyze the .hex file with the aid of some information from the .sym file (ISRs, specially handled functions, etc).

I also needed mine to perform stack use analysis for one or more tasks so it is invoked with the address of the root of the call tree that is to be analyzed.

My implementation partially solves the jump table problem by allowing the user to enumerate the possible destinations (either explicitly or by naming a data structure containing the addresses). Moreover, it provides a way for users to specify the stack depth of routines whose stack use would otherwise be indeterminate (due to recursion, presence of ijmp/icall, etc.).

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net