Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

Stack and Heap Access Question

Options
  • 13-01-2016 10:26pm
    #1
    Registered Users Posts: 8,090 ✭✭✭


    It is more efficient to use a global variable than to pass a parameter to a function. This eliminates the need to push the parameter onto the stack before the function call and pop it back off once the function is completed. In fact, the most efficient implementation of any subroutine would have no parameters at all.
    Stack vs Heap Pros and Cons
    Stack
    • very fast access
    • don't have to explicitly de-allocate variables
    • space is managed efficiently by CPU, memory will not become fragmented
    • local variables only
    • limit on stack size (OS-dependent)
    • variables cannot be resized
    Heap
    • variables can be accessed globally
    • no limit on memory size
    • (relatively) slower access
    • no guaranteed efficient use of space, memory may become fragmented over time as blocks of memory are allocated, then freed
    • you must manage memory (you're in charge of allocating and freeing variables)
    • variables can be resized using realloc()
    http://gribblelab.org/CBootcamp/7_Memory_Stack_vs_Heap.html

    First quote states that globals are quicker than using the heap. Second states that the stack is much quicker.

    Is there a difference between parameter passing and local variables - even though they are both on the stack? I thought the difference would be nothing as they both use the same memory structure of the stack. Whereas globals use direct addressing which is slower.

    What am I missing here? Both quotes are in relation to C.


    Thanks.


Comments

  • Registered Users Posts: 13 rwsz365


    The first function on that page the argument is passed by value, so the value is copied into the function and is a local variable to that function. Any changes to that variable are entirely local to that function. There is the additional overhead of copying the value, which is why it can be slower for items like large arrays as the cost of copying it is greater than the gain of it being on the stack even if it can fit there.


  • Registered Users Posts: 8,090 ✭✭✭funkey_monkey


    Thanks - I should have said that the first quote is from Programming Embedded Systems in C and C++ by Michael Barr.


  • Registered Users Posts: 1,275 ✭✭✭bpmurray


    When you're talking about embedded systems, you want to shave as much off overhead as you can, so this discussion is relevant. On the other hand, if you want "nice" code, globals are looked on as poor practice - the C++ idea of data hiding as applied to C. However, aesthetics apart, if you want large blobs of data to be moved around, dynamic allocation from the heap is obviously the way to go, but the pointer should still be passed only on a need-to-know basis.


  • Closed Accounts Posts: 5,361 ✭✭✭Boskowski


    Like the previous poster said the context of embedded is really important here. In general application programming all of those quotes are just poison, but then things like stack and heap are not too much of a consideration there cos there's plenty of all of that. In embedded however resources like memory and cpu are often scarce and clean programming principles often go out the window.

    Anyway first quote isn't saying what you think its saying. What the first quote is saying is that when using parameters you're pushing values onto the stack and then potentially back, whereas a global variable's name (and therefore address) is simply known to any function so it can be directly used. This is getting more important the bigger the data gets, like for instance a big struct as opposed to a couple of integers.

    Difference between parameters and local variables is that parameters are what an outside user of a function provides the function with whereas local variables are local to that function and not accessible (not existent in fact) outside the scope of the function.

    Of course you can also just pass references/pointers which can refer to data both on the stack and on the heap. Just to make matters more confusing. ;)

    The good news is its actually not all that confusing but you need to understand a few basic principles. I recommend the classic C bible from Kernighan Ritchie to understand all that. Once you have the basics of globals, locals, scope, static & dynamic memory allocation, pointers and references it will make more sense to you.


  • Registered Users Posts: 40,038 ✭✭✭✭Sparks


    It is more efficient to use a global variable than to pass a parameter to a function.
    And right there my evaluation of that person's professional ability landed in the toilet and started swimming downwards.

    Unless you're doing embedded programming on a 4-bit micro in assembler, global variable efficiency versus stack efficiency is not something to worry about (and in this context, passing pointers to shared blocks of memory is not the same thing as using a global variable because nothing else in the system has that pointer). Seriously, if you're worrying about the cycles to pop stuff off the stack, you're either working on a low-end PIC chip or you're wasting time (hell, anything actually fast - and ARM cores aren't exactly unicorns in embedded work - is pipelining anyway and cycle-saving is not exactly straightforward). Your co-workers waiting for you with torches and pitchforks one morning because they've been up all night debugging a threading issue caused by you using global variables, on the other hand...


  • Advertisement
  • Registered Users Posts: 768 ✭✭✭14ned


    Sparks wrote: »
    And right there my evaluation of that person's professional ability landed in the toilet and started swimming downwards.

    Unless you're doing embedded programming on a 4-bit micro in assembler, global variable efficiency versus stack efficiency is not something to worry about (and in this context, passing pointers to shared blocks of memory is not the same thing as using a global variable because nothing else in the system has that pointer). Seriously, if you're worrying about the cycles to pop stuff off the stack, you're either working on a low-end PIC chip or you're wasting time (hell, anything actually fast - and ARM cores aren't exactly unicorns in embedded work - is pipelining anyway and cycle-saving is not exactly straightforward). Your co-workers waiting for you with torches and pitchforks one morning because they've been up all night debugging a threading issue caused by you using global variables, on the other hand...

    It's even worse than that again, and I'll put on my hat as a Boost C++ libraries developer and former representative of Ireland on ISO standards right now:

    Parameter use can be deduced to have no global effect whilst global variable use always has global effect

    What this means is that the compiler can never elide use of global variables because by definition, they may have been changed since the last time you looked at them. That requires the compiler to treat global variable use points as AST-to-code sync points, a bit like calling fsync() on the AST. In other words, you force the compiler to emit code.

    Most parameter usage however can be deduced by the compiler to have no global effects on memory. Therefore no code need to be emitted at all. This is a big reason behind the restrict keyword in C and the use of const by-value copies in C++ 11 - the former is when the programmer tells the compiler explicitly to not worry about dependency state changes, the latter lets the compiler elide the copy completely but to assume the two "copies" are distinct (and hence why C++ has no need for a restrict keyword).

    tl;dr; the linked page is completely wrong. The C++ which optimises best is that which is all inlined and never touches a syscall, extern function nor global memory. I in fact wrote a Boost library which explicitly uses these tricks to turn thousands of lines of complex C++ into single emitted assembler instructions, and it can be seen at https://github.com/ned14/boost.outcome with per-commit unit tested proof of this single opcode reduction ability at https://github.com/ned14/boost.outcome/tree/master/test/constexprs.

    Niall


Advertisement