Advertisement

TypeID/TypeName : virtual vs memory

Started by May 26, 2018 10:04 AM
5 comments, last by frob 6 years, 3 months ago

Hi,
When you need a factory or identify multiple type you have a function to get the type ID and type name.
First I did just a virtual which return the value then I switched to a private variable that the base class constructor set.
Using virtual cost more performance, without virtual you have more memory used.
Any opinion about this ?
Thank you

Did you actually profile this?

Anyway, I wouldn't worry about stuff like this, you're not going to win any performance problem by eliminating a few bytes or one virtual dereference.

Advertisement
1 hour ago, Alberth said:

Did you actually profile this?

Anyway, I wouldn't worry about stuff like this, you're not going to win any performance problem by eliminating a few bytes or one virtual dereference.

In fairness, the performance implications of virtual calls doesn't extend to just the virtual function dereference. In many cases the use of virtual functions for polymorphism specifically can prevent the compiler (or linker, if you have link-time optimization enabled) from inlining the function call because by definition, it doesn't know at compile time which implementation will be called. This may be true even in cases where it's fairly obvious from the programmer's perspective which implementation will be called, as the compiler needs to be able to prove to itself that a particular implementation will be used in a specific spot to inline it.

But yes, did you actually profile this and discover that the virtual call was the cause of your performance problems?

Did you try restructuring your code to move any problematic virtual functions out of inner loops?

It's hard to evaluate whether this was an actual issue without code...

4 hours ago, Alundra said:

Any opinion about this ?

If you're ever in the situation where you have a pointer to an abstract interface, but need to call a virtual function that's basically asking "what kind of object are you, really", then you're abusing/breaking the rules of OO. There's probably a different design you could use where this problem doesn't exist in the first place.

4 hours ago, Alundra said:

Using virtual cost more performance, without virtual you have more memory used.

Using virtual adds 8 bytes to each instance (assuming you weren't using it before). Accessing any memory (whether it's the 8-byte vtable pointer, or the 1? byte type ID) can be 10x more expensive than a virtual function call, if that memory is cold.

This is a micro-optimisation, and micro-optimizations depend on all of the precise, specific nuanced details of the specific program that you're optimizing, so there's no general rule you can apply here that will tell you which one will be nanoseconds faster than the other.

This is basically an ActorComponent, the renderer look at the ID to use the correct rendering function :
StaticMesh / AnimatedMesh / ParticleSystem / Billboard...
Theorically it can be called only once when rendering the frame if the code is correctly structured.
I changed that 2 years ago and I was just thinking the last day about it and then asked here to have opinion.
Unfortunately I didn't looked the performance before and after at this time...

On 5/26/2018 at 12:12 PM, Alundra said:

This is basically an ActorComponent, the renderer look at the ID to use the correct rendering function

That's a sign of a non-scaling design.  It means the design is closed to extension.  It can work with a small personal project, but the general advice will be "don't do that".

Generally you should pass commands to objects. Instead of asking what type it is so the caller can know what to do, ask the object what it's method should be. Then either pool them up for batch processing, or invoke the method directly.

 

Written differently, don't do this:

if( actor->GetType() == ActorType::Wizard) { ... do wizard thing ... }

else if (actor->GetType() == ActorType::Warrior) { ... do warrior thing... }

else if (actor->GetType() == ActorType::Thief) { ... do thief thing... }

...

Do this instead:

actor->DoTheThing();

 

or in your case:

renderFunc = thing->GetPreferredRenderFunction();

 

On 5/26/2018 at 12:12 PM, Alundra said:

Theorically it can be called only once when rendering the frame if the code is correctly structured.

If you're talking about theoretic performance, with some template magic it can be turned into a non-virtual function and a const static value, each class will need to specialize the value to be unique to it. If the compiler makes some constexpr optimizations even that can potentially become a no-op directly looking at the constant value.  It could be an integer value that is part of the class/struct with a non-virtual template function that returns that value directly.

 

But out in the real world, it is common enough to have a member variable and options are set by data.  Designers, artists, and other implementers will use tools to select the right data value from a list. The data gets read in and processed, and whatever data value happens to be there at run time is the choice that is made.

This topic is closed to new replies.

Advertisement