Sign in to follow this  
rpiller

C++ memory questions

Recommended Posts

I use C++ as a hobby and .NET professionally so I can code in C++ as my hobby in game development but I don't understand 100% the insides and out of memory. I think I have a decent understanding but I want to ask some questions and give how I think things work (over reading forums and other thing about it) and maybe someone could be as kind as to tell me if I'm mistaken.

 

 

1) Memory created on the stack is created faster and accessed faster (therefor runs faster) than memory created on the heap.

 

2) There is only so many Meg's of stack memory per application, but heap can grow and shrink.

 

3) stl containers actually store the objects they contain on the heap. it doesn't matter if the type you have is a pointer or not. ie (list<Object> vs list<Object*>). If I'm filling this list myself ALL objects will be created on the heap meaning the speed penalty between the stack/heap exists.

 

4) Normal arrays that are not storing pointers ie (Object obj[10]) are stored on the stack no matter what.

 

5) I thought I heard that if the object you are inside was created on the heap then the variables that it creates are also stored on the heap even if they aren't pointers ie:

 

class Object
{
};
 
class Entity
{
private:
   Object o;
};
 
Entity* e = new Entity();
 
//e->o is actually created on the heap instead of the stack because it's parent object (Entity) was created on the heap

 

6) So given that above isn't that far off, that means to truly squeeze performance of both loading times and speed, one should try to avoid the heap if possible. The problem with that being that you only have so much space on the stack (maybe 64-bit eases this pain a lot?) and that you have to know how many objects you'd need. My question about knowing is that very few games actually have unlimited amounts of any objects. So you could store your objects in normal arrays that would be predefined/max size and have code for reusing "old"/"deleted" objects. This would mean you are most likely wasting memory but at the benefit of speed. Is that trade-off ever worth it games? I mean a benefit to this is that you don't have to worry about memory management or leaks. I understand most parts of a game (audio/visual) will use the heap and has too, but I'm more referring to the gameplay code (the code I'm actually writing because I use an engine for all the other stuff) instead of the resource management.

 

 

Thanks for reading

Share this post


Link to post
Share on other sites

But there is a speed difference in allocation right, meaning loading times would be faster if everything that could would be stored on the stack vs heap? Again though because most times we don't know how many objects we would sacrifice memory by pre-allocating everything on the stack, but I would think loading would be greatly increased. We all hate loading times right smile.png

 

I remember I was testing a 2D tile game where I would create Tile objects dynamically for each element in the 2D array (trees, etc). When I was using new Tile on this 2000x2000 2D array it took like 10 mins or something like that to finish (I don't remember the exact numbers but it was a long time). When I switched to stack memory for this it was a couple seconds. So the difference between Tile* map[2000][2000] vs Tile map[2000][2000] was massive. Of course that changes how I was going to code things because I was using polymorphism for the Tile objects and couldn't when I changed to not using a pointer for the objects.

Edited by rpiller

Share this post


Link to post
Share on other sites


You'd be better off making one big allocation that contains the entire array of tiles, and using some other technique than virtual functions for polymorphism (i.e. switching behavior based on a type field in the tile, or something). 

 

I agree, but the attractiveness of polymorphism is powerful :) 

Share this post


Link to post
Share on other sites

The stack pointer is in a register. If you allocate something on the stack, it's assigned an offset. There is no actual runtime allocation of memory that incurs a cost, just the address calculation done at compile time. So when you use map[x][y] from the stack, the compiler replaces that with something like stack register + offset to map + x * sizeof(Tile) + y * sizeof(Tile) * 2000. That numerical result is computed at compile time, so there is no runtime cost to using stack memory.

 

Even your "Tile* map[2000][2000]" line of code is not using the heap. That is placing 4 million Tile pointers on the stack. When you call new to allocate space for one of the elements of the map 2D array, that is the first heap memory you're using. For performance, you want to minimize the number of times you call new (or malloc, etc.). The new operation is very slow, slow enough that many, many games reinvent the wheel and write their own memory allocation functions.

 

In your situation, I'd probably do:

const int numTilesX = 2000;

const int numTilesY = 2000;

Tile* map = new Tile[numTilesX * numTilesY];

and access any element as map[x + y * numTilesX]

 

I use single-dimensional arrays as often as possible. I just find them easier to debug, and I'm a bad enough programmer that I spend a lot more time debugging than writing new code =)

Share this post


Link to post
Share on other sites

If it helps, think of it in terms of the struct keyword vs class keyword in C#.  Any local variable or class member in C++ automatically acts like a C# struct.  If you explicitly allocate on the heap (it'll never happen automatically, except when some class you use is doing it internally, like most STL containers) then it's like a C# class.  Likewise, the performance in C++ is not too far off from C#: don't allocate things you don't need to allocate.  C# makes it harder to avoid allocations compared to C++ in exchange for making it easier deal with.  You really need a clear understanding of the stack and heap for high-end C# programming, too, so you might want to take the time to read some texts on the topic.

 

Video classes on pointers and allocation: https://www.youtube.com/playlist?list=PL2_aWCzGMAwLZp6LMUKI3cc7pgGsasm2_

 

Articles and online books on the topic:

http://www-ee.eng.hawaii.edu/~dyun/ee160/Book/chap14/subsection2.1.1.8.html

http://gribblelab.org/CBootcamp/7_Memory_Stack_vs_Heap.html

http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap

 

I'm sure you could find more with a little Googling if those aren't cutting it for you.

Share this post


Link to post
Share on other sites
Hi there. I don't think it's that slow to allocate memory. My last 2d rts game I allocated all objects with new and deleted them and I had no slow downs or any thing you could notice. And that could have 8 players with 800 units each plus.

Share this post


Link to post
Share on other sites

Hi there. I don't think it's that slow to allocate memory. My last 2d rts game I allocated all objects with new and deleted them and I had no slow downs or any thing you could notice. And that could have 8 players with 800 units each plus.

 

If you mean allocating each unit separately, it could make a huge difference if you used pool allocation instead when it comes to creating and destroying units, as well as processing them (due to cache being utilized better)

 

The creation and destruction of units probably isnt a problem here though because i doubt you would be doing thousands of allocations per second. Its more the processing part that would matter here.

 

So allocation isnt horribly slow itself, but compared to the alternatives it is.

 

As an example i had implemented my sparse quadtree using std::function (so i can use lambdas to do operations on it) and std::vector, and when i replaced std::function with a template parameter and applied some .reserve() to the vectors, the performance improved at least tenfold.

Share this post


Link to post
Share on other sites

The basic bottom line is not to assume the stack is faster than the heap.  Use the stack how it is supposed to be used (for small local variables) and use the heap how it is supposed to be used (for large data, data of changing or unknown sizes, etc.) and learn general proper performance practices.

This alone would sum up the point pretty well, even ignoring the entire rest of the information of the post.

If anything a more realistic point to make would be that there is almost never going to be a situation where you are suffering performance wise simply because you made an allocation on the heap vs the stack, if anything the problem is usually that you're making memory allocations on the heap in an extremely inefficient way.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this