Typecasting Performance Question

Started by
38 comments, last by MaulingMonkey 18 years, 9 months ago
In my application I currently have seperate functions to create the resources (for example CreateTexture, CreateIndexBuffer, CreateSample etc.), and each of these functions returns a pointer to the resource created. Now this works fine, but internally it is a bit of a mess. The application has to keep track of all the resources, and there are a lot of different types, so there are a lot of different functions, making it difficult to maintain and update. Im thinking of replacing the seperate functions with a single function CreateResource, that returns a pointer to the resource's base class. texture = (CTexture*)CreateResource(EResource_Texture); I am concerned about the use of the typecast, as now there will be a lot of type casts (internally, the game will save a pointer to the resources base class also, so when updating and deleteing etc, it will need to typecast also). Will having a large number of typecasts be a performance issue, or will it not be noticable? Having a cleaner internal structure is important to me, but a faster application is of more importance. Any advice or information would be useful here. Thanks Daisy
________________________
Pretty In Pink
Advertisement
well at first you won t load tons of resources at runtime right? only in the beginning so typecasts shouldn t hurt


another thing i want to mention, in assembly you don t have any other types than byte, short, word and long and casting your baseclass pointer to another subclass pointer just tells the compiler how to tread the memory your pointer refers to its just plain data

so i dont think that it hurts at all performance wise as long as your compiler uses optimization

i dont know how it virtual functions are implemented in c++ but other than that i see no reason why it should hurt performance

maybe it speeds your code up a little bit because you reduce the amount of instructions stored in the binary, but this should be pretty OS depentant
http://www.8ung.at/basiror/theironcross.html
Quote:Original post by Basiror
well at first you won t load tons of resources at runtime right? only in the beginning so typecasts shouldn t hurt


At the moment yes, all resources are loaded at run time, but as it is a streaming application, it might be, in the future, that resources are loaded as and when, so resources could be loaded during runtime if needed.

But what I am concerned about is the internal updates. For example, animating textures are updated automatically within the application. Now that textures will be stored as CBaseResource's, then each and every frame needs to be type casted, and this is the performace issue I could be concered about.

Thanks
Daisy
________________________
Pretty In Pink
I'm pretty sure it won't have any effect.

You are typecasting different types of pointers... but a pointer is still just a number. When you cast between fundamentally different types such as ints and floats, a converstion must be done as the same number is stored differently in a float. With pointers, there is no such conversion taking place.

The type of pointer you are dealing with is handled at compile time and is integrated automatically with vptr tables for each derived class. So typecasting is not actually an operation in this case. When you invoke any abstract methods on the class CTexture, a check will be done to determine the correct function to call (in the correct subclass). I think that might add a little overhead but it is probably negligable.

That is a really common thing to do so I wouldn't worry about it even if there were some overhead. If it greatly simplifies the design, then go for it. Also, unless you are doing it thousands of times per second, don't even think about it anymore.

I could be wrong though... anyone else?
Quote:Original post by PrincessDaisy
Im thinking of replacing the seperate functions with a single function CreateResource, that returns a pointer to the resource's base class.

texture = (CTexture*)CreateResource(EResource_Texture);


Don't use C style casts in C++, for one thing C style casts do not work on polymorphic types when casting at runtime, use the C++ family of cast operators, in particular dynamic/static_cast for polymorphic types.

Quote:Original post by PrincessDaisy
I am concerned about the use of the typecast, as now there will be a lot of type casts (internally, the game will save a pointer to the resources base class also, so when updating and deleteing etc, it will need to typecast also).


I smell a design stench.

Quote:Original post by PrincessDaisy
Will having a large number of typecasts be a performance issue, or will it not be noticable?


There are different kinds of casts, in C++ there are different cast operators which you should be using, the one that may cost noticeable preformance is dynamic_cast because it can traverse a type hierarchy at runtime, you can think of it as DAG traverser. The efficiency of dynamic_cast depends on the platform on some the cost may be negligible but on others painfully noticeable, in other words you need to profile to find out.

dynamic_cast is used when you have no idea what the type is referred to by a pointer/reference to super-type so it will nearly always cost you something, however if your 100% sure what the type is then you can use static_cast which has no cost at run-time but your program will most definitely crash if your wrong about what the type is.

Really though your design smells bad to me.

[Edited by - snk_kid on July 18, 2005 4:51:14 AM]
Since your'e doing a "throw the type system out the window" style cast using the C-cast sledgehammer it won't cost you anything but loads of debugging time and potentialy henious type-errors at runtime.

Now some people (like me) would call that quite a high cost to pay for a bad design, but the runtime cost will be zero. If you internaly want to keep track of all reasources that's nice use a common base for that but don't force it down the throat of your clients.

I would strongly advice you to keep your type-safe factory methods that you have or if you somehow do thing that it's a sane idea to have a singe CreateResource function at least then induce typesafety using checked dynamic_cast.

And deletion through base pointer shoulnd't be a problem as long as you remember to declare the destructor virtual (else you'll summon the beast of undefined behaviour).

Generally when working in C++ loosing (too much) type-information can be a really bad thing, or smell.
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
Quote:Original post by PrincessDaisy
Quote:Original post by Basiror
well at first you won t load tons of resources at runtime right? only in the beginning so typecasts shouldn t hurt


At the moment yes, all resources are loaded at run time, but as it is a streaming application, it might be, in the future, that resources are loaded as and when, so resources could be loaded during runtime if needed.

But what I am concerned about is the internal updates. For example, animating textures are updated automatically within the application. Now that textures will be stored as CBaseResource's, then each and every frame needs to be type casted, and this is the performace issue I could be concered about.

Thanks
Daisy


as i already said your pointer is just a address to some memory and the type of the pointer tells the compile what operations to perform so there shouldn t be any performance decrease
http://www.8ung.at/basiror/theironcross.html
Quote:Original post by snk_kid
Really though your design smells bad to me.


Ok... What smells so bad?

I'll give you an overview of the design and you can tell me what you suggest.

Each resource is stored within a list, so the application can keep track of all loaded resources. So we have a texture list, index buffer list etc.

Currently, I have a large number of these lists, as the list stores a pointer to all the resources so for example

List<CTexture*>
List<CIndexBuffer*> etc.

Some of these resources need to be updated per frame (anaimating textures is an obvious example), and this shouldnt be up to the front end, so internall, we have a loop calling Update for each texture.

When we call CreateTexture, CreateIndexBuffer etc. the new resource is added to the appropriate list, and the resource is returned.

So far, what is the problem?

With a new structure, I would have a larger array of lists, instead of a long list of seperate lists.

List<CBaseResource*> resources[No_Resources];

When CreateResource is called, then the resource is created and added to te appropriate list (referenced via the enum). And the base resource is called.

Obviously, the Updates and Draws still need to be called and this is where the type case comes in.

Now if this sucks, please explain why. The lists are currently seperated into controlling classes, and handled quite will (though not very elegantly, which is why I am suggesting the new system). If you can justify your response I will be more than willing to listen to any suggestions.



Thank you for the advice on the static/dynamic casting though, as this is something I have not have any experience with.

Thanks
Daisy
________________________
Pretty In Pink
Quote:Original post by Basiror
Quote:Original post by PrincessDaisy
Quote:Original post by Basiror
well at first you won t load tons of resources at runtime right? only in the beginning so typecasts shouldn t hurt


At the moment yes, all resources are loaded at run time, but as it is a streaming application, it might be, in the future, that resources are loaded as and when, so resources could be loaded during runtime if needed.

But what I am concerned about is the internal updates. For example, animating textures are updated automatically within the application. Now that textures will be stored as CBaseResource's, then each and every frame needs to be type casted, and this is the performace issue I could be concered about.

Thanks
Daisy


as i already said your pointer is just a address to some memory and the type of the pointer tells the compile what operations to perform so there shouldn t be any performance decrease


If you do anything like that then your asking for trouble, as i already mentioned C style cast can not do type conversions at run-time, its not for polymorphic types, it does not understand/care what they are. C style casts in C++ typically are (depending on the context) equivalent to static_cast, reinterpret_cast, or const_cast.

dynamic_cast is a type DAG traverser it can traverse a hierarchy of related types at runtime and in some simple cases it will do it at compile-time. It will inform you if a traversal fails by returning 0 for pointers or throws a bad_cast exception for references. The cost of dynamic_cast depends on the platform, it maybe negliable or painfully noticeable you need to profile to find out.

Like said before generally don't use C-style casts in C++
Could you please explain the reasoning behind thinking that keeping one gigantic list with all resources and type-switching on each entry would somehow be advantageous to keeping fine grained lists and in a type safe manner processing only exactly thos elements that need to?

The old system from a design point at least is type-safe and efficent whereas the new proposed system throws type information right out the window would require potentially expensive operations later to regain it and doesn't provide any clear benefit that I can see.

What are your problems with the current system? Having to many lists? Duplicating behaviour?
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats

This topic is closed to new replies.

Advertisement