Advertisement

Small question about singletons created on the stack

Started by July 25, 2018 10:46 PM
19 comments, last by Gnollrunner 6 years, 1 month ago

I'm reading the book "Game Engine Architecture" where the author suggests declaring singletons as global variables, and later initialize each of them inside main() in the correct order.

Example from the book:


RenderManager gRenderManager;
PhysicsManager gPhysicsManager;
AnimationManager gAnimationManager;
TextureManager gTextureManager;
VideoManager gVideoManager;
MemoryManager gMemoryManager;
FileSystemManager gFileSystemManager;
// ...
int main( int argc, const char * argv ) {
	// Start up engine systems in the correct order.
	gMemoryManager.startUp();
	gFileSystemManager.startUp();
	gVideoManager.startUp();
	gTextureManager.startUp();
	gRenderManager.startUp();
	gAnimationManager.startUp();
	gPhysicsManager.startUp();
	// ...
	// Run the game.
	gSimulationManager.run();
	// Shut everything down, in reverse order.
	// ...
	gPhysicsManager.shutDown();
	gAnimationManager.shutDown();
	gRenderManager.shutDown();
	gFileSystemManager.shutDown();
	gMemoryManager.shutDown();
  
	return 0;
}

Isn't it risky to create all these singletons on the stack? I mean, depending on the situation won't I get a stack overflow or something like that?

I apologize if it's a silly question, I'm just a little confused about the topic of where and when to allocate memory.

It's not a bad question - but you'll need to do A LOT more than that to overflow the stack. No need to worry about that in this instance.

Advertisement

Those aren't singletons. They're globals, and they're actually stored on the heap.

Even if they were on the stack (i.e. local to the main function), you'd probably be fine (assuming those classes aren't doing something stupid like allocating several gigs of memory).

if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight
52 minutes ago, ChaosEngine said:

Those aren't singletons. They're globals, and they're actually stored on the heap.

Not quite. Globals in C++ aren't stored on the heap or the stack, they're stored in the executable's "data segment".

1 hour ago, ChaosEngine said:

Those aren't singletons. They're globals, and they're actually stored on the heap.

Even if they were on the stack (i.e. local to the main function), you'd probably be fine (assuming those classes aren't doing something stupid like allocating several gigs of memory).

 

20 minutes ago, Oberon_Command said:

Not quite. Globals in C++ aren't stored on the heap or the stack, they're stored in the executable's "data segment".

You guys are right. It's not the stack, but it's not the heap either. Also, I should apologize for the mistake, since in the book the author doesn't mention anywhere that it's on the stack, so it's a mistake on my part.

About the "data segment", if these globals contain any member pointer variables, and I allocate memory dynamically on these "startUp()" calls, I suppose this newly allocated memory will reside in the heap then. Since they're basically on different memory regions, will dereferencing the pointer be slower?

 

1 hour ago, Oberon_Command said:

Globals in C++ aren't stored on the heap or the stack, they're stored in the executable's "data segment".

I stand corrected. Man, my C++ game is slipping.... I really should have known that.

57 minutes ago, Jiraya said:

I suppose this newly allocated memory will reside in the heap then. Since they're basically on different memory regions, will dereferencing the pointer be slower?

Short answer: yes.

Longer answer: probably, but by how much and whether it actually makes any kind of noticeable difference will depend on the usage scenario. 

if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight
Advertisement
3 hours ago, Jiraya said:

About the "data segment", if these globals contain any member pointer variables, and I allocate memory dynamically on these "startUp()" calls, I suppose this newly allocated memory will reside in the heap then. Since they're basically on different memory regions, will dereferencing the pointer be slower?

It's not that simple. If you access the global data often enough, it sticks in the cache, and access is fast. Cache doesn't care about memory segments, it cares about data access patterns at memory address level.

Given that you likely perform more than one read or write operation in your blob of allocated memory, I'd say focus on that rather than a single dereference jump to get to the blob.

And of course, a bad algorithm to perform the computation itself dwarfs all your memory access optimizations so get that right first.

There are no memory "regions", it's all identical and equally fast RAM in the address space of your process; reasons for preferring global variables to the stack as a singleton location have to do with rather formal aspects of C++:

  • Stack space could be arbitrarily limited, there's no reason to waste it.
  • Global variables are global, while local variables of main() could only be accessed through pointers everywhere else.
  • Heap use requires pointers and error handling
  • Reduced hypocrisy

Omae Wa Mou Shindeiru

On 7/26/2018 at 4:28 AM, Jiraya said:

. Since they're basically on different memory regions, will dereferencing the pointer be slower?

 

It might be, but on the other hand you don't really know what a given CPU will do.  They can generally load more than a single contiguous block of memory into cache anyway. Not to mention even if you put them on the heap there is no guarantee they will be close to each other in memory, although typically allocation of stuff at the beginning of a program tends to be next to each other.  You could even make it so if you wanted to put in the effort, by the judicious use of placement new. 

On the other hand if you declare pointers instead of values in global memory you will probably have just moved the problem. The CPU will now have to go to global memory anyway just to get the pointer and then still go to the heap so their might still be not much point to it. In short...... I wouldn't worry about it :D


 

Thanks everyone, you were really helpful.

Also, if anyone stumbles in this topic in the future, I've found a link with some good resources about memory and cache:

https://gist.github.com/ocornut/cb980ea183e848685a36

This topic is closed to new replies.

Advertisement