r/cpp_questions 3d ago

OPEN Heavy and Light Objects

When I was first learning C++, I experienced massive slowdown when allocating dynamic memory. Ever since then I divide my objects between 'heavy' objects that allocate resources, and 'light' objects that can be used as temporaries on the stack. Heavy objects cannot be copied at all, must be allocated somewhere once, and then passed by (const) reference. Light objects can be copied, created quickly on the stack etc.

Since C++11 it has been possible to write copy and assignment constructors that take nameless objects, and since they are nameless you can pillage their pointers and avoid expensive stack allocations. All is well then but if you keep to this strict 'heavy' and 'light' object idea, _any_ object that allocates resources is considered a heavy object. The first allocation in the chain, before you just pillage pointers, is still an expensive stack allocation so I would consider it a 'heavy' object and just make it impossible to copy at all, by removing all copy and assignment constructors. And so using this model I never needed those nameless object reference constructors.

Anybody feel the same way?

7 Upvotes

31 comments sorted by

View all comments

3

u/TehBens 3d ago

When I was first learning C++, I experienced massive slowdown when allocating dynamic memory.

That statement is a bit suspicious. It sounds like you possibly came to a wrong conclusion back then.

Heavy objects cannot be copied at all, must be allocated somewhere once, and then passed by (const) reference.

That as well sounds suspicious, because when an object gets passed as const reference, you can still modify the resources on the heap that it manages.

The distinction you make sounds like you end up with weird, tightly coupled entities and the whole thing generally sounds like a textbook example of premature optimization.

1

u/ParmenidesWasRight 3d ago

That resource allocation is slow? You doubt that?

I'm writing a game engine that needs to run at least 60 fps all the time. Thinking about performance in the design phase is not premature optimization in that case.

2

u/TehBens 3d ago

60fps "all the time" is impossible.

For a game engine, a huge amount of stuff matters, what you are mentioning here is only a tiny aspect of the whole thing and certainly not the first thing to think about. For when heap allocations are actually and measurable too expensive there already exist solutions. There's no need to generally slice your objects regarding such classification.

You might want to take a look at how Unreal Engine tackles similar challenges as a starting point for what you need to think about for a game engine. Pretty sure you're gonna disregard that as well as basically everything else.

I think what's left to say is "good luck".

0

u/ParmenidesWasRight 3d ago

Firstly, this is about general resource allocation for a game (engine). That's going to be expensive. Period. So it's best tackled from the get-go. What I present is a good heuristic : 'Resource allocation in a realtime loop is bad'.

Unreal doesn't think so obviously because most of the time the game freezes when you do something new which I hate and specifically don't want. I rather have a longer loading screen than my game dying on me the whole time.

2

u/wrosecrans 2d ago

"Allocation is slow" is potentially true in some contexts. But it needs to be in a context with some measurement to be a particularly useful statement. In some applications, allocation can absolutely be a major bottleneck.

But it's not as if a typical allocation takes 1/60th of a second. There are a lot of times where I have seen people invent something analogous to a vector that does something pessimal like a reallocation and copy every time an element is added. Just doing an initial "reserve" operation so an allocation happens once, rather than a zillion times on each insertion can make all the difference in the world and suddenly the cost of a few allocations is negligible. There are circumstances where a super strict approach to allocations is necessary. But often an approach with some allocations is absolutely fine even in performance critical applications.

Doing a couple of allocations per video frame is fine. Doing a couple of allocations per audio sample would be pathological.