Archived

This topic is now archived and is closed to further replies.

vesoljc

my own RTTI

Recommended Posts

would a custom RTTI system, based on std::bitset, be worth the trouble, is it faster than typeid? AFAIK, bitwise operations are fast, really fast i would create a base class, which would contain a bitset and in each derived class i would add a new flag (in constructor), giving my objects type id, ie: is_logable, is_whatever, etc.. pros/cons?

Share this post


Link to post
Share on other sites
Yeah like for a CGameObject base class you would only need 3 public methods:

virtual void init();
virtual void update(long delta_t);
virtual void do_event(Event e);

and Event would be overridden to do EVERYTHING for your objects depending on its types. Like for a bullet event could be 'set velocity' but for a scenerery object chair 'set velocity' might not have an effect.

[edited by - sagwagon on January 25, 2004 1:34:20 PM]

Share this post


Link to post
Share on other sites
When in doubt try it yourself and see.

This seems fruitless however because I really doubt that RTTI would be *the* bottleneck in your application. If it is, then its probably a sign that you are abusing it. Since it probably isn''t the bottleneck, you can focus on those things that ARE slowing you down, not the ones that ''seem'' slow to you because you''ve read they are.

Share this post


Link to post
Share on other sites
@antareus

i understand ur point...
but if u(i) think that everything is too slow, why not "now" think about it? it's not like i'm gonna devote a month to it...

one more question:
what operations go on in built in RTTI?

[edited by - vesoljc on January 25, 2004 4:58:40 PM]

Share this post


Link to post
Share on other sites
My hunch is that what you''re planning would cause your application to perform worse overall than using native RTTI. The reason being is that you intend to embed type information in your objects on a per-object basis which will increase overall object size smacking you with decreased memory performance.

Plus, wheres the advantage? Once you''ve determined that your class is loggable, you''re going to need some kind of cast to get at it''s logging function anyway, which usually means a dynamic_cast to a logging interface.

Nevermind the small fact that capability queries are usually a bad idea in the first place.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by Raloth
RTTI is bad design in almost every case. Can''t you come up with some basic class structure instead?


In a lot of cases it''s bad and the needed behavior can probably be handled with some virtual functions, but it''s pretty handy when serializing/deserializing classes to/from a file... you have to know what class to construct when loading, which means you have to save some RTTI info when saving.


Share this post


Link to post
Share on other sites
@SiCrane

my idea allready needs a status made out of bitwise flags (sort of a stete machine) and as such imho, the memory impact would not be so big. few bytes up or down... it''s still under 1k

Share this post


Link to post
Share on other sites
quote:

i understand ur point...
but if u(i) think that everything is too slow, why not "now" think about it? it''s not like i''m gonna devote a month to it...


Its one thing to think about proper data structures and design up front. Personally the less I have to write the more confident I am in my program. Thats why I use all STL stuff.

I''m not seeing much benefit here -- which is why I slammed you in the first post. Bitwise ops are fast, yes, but you''re splicing hairs here.

quote:
the query rate would not be high...

Right, so you''re not needing the performance here. You said it yourself.

Share this post


Link to post
Share on other sites
All that is involved with RTTI is checking the vtable pointer. It is compared against the vtable address for the class you are trying to cast to when you do dynamic_cast. It doesn''t matter if your comparing bitsets or pointers, they will not be different in speed. unless the bitset is more than sizeof(void*).

Share this post


Link to post
Share on other sites
dynamic_cast involves much more than simply comparing vtable pointers. I encourage you to look at the disassembly of a dynamic_cast expression on your compiler. In MSVC 7, it involves a function call to __RTDynamicCast, a private function that takes five parameters. Just the call overhead alone is probably worse than a simple vptr comparison. However, __RTDynamicCast is itself a fairly non trivial function, which itself calls additional internal runtime library functions, some private and some not. One of the called functions is strcmp() which should give you some idea of the cost of dynamic_cast.

Share this post


Link to post
Share on other sites
Why would it work?

Consider a situation where I have two independent abstract base classes ABC1 and ABC2. Now let''s say I have this snippet:
ABC1 * p = GetAnABC1();
ABC2 * q = dynamic_cast<ABC2 *>(p);

p''s vptr could never equal the address of ABC2''s vtable. It''s just not possible. Yet this is a perfectly valid dynamic_cast expression that could yield a non-null pointer. Therefore comparing vtable addresses isn''t sufficient.

Share this post


Link to post
Share on other sites
RTTI is slow. Or at least it can be; I believe the speed is unspecified by the standard. Basically, it likely involves walking through the inheritance tree looking for a match. Since C++ supports MI, it is may end up searching a decent sized graph. Now, again, this is all implementation defined.

I have worked with a fairly simple implementation in a large codebase. Even in fairly simple cases involving about 20 classes, 3 levels of SI deep, the in house RTTI implementation was about 10 times faster than the vc6 C++ RTTI. I haven''t done any profiling with vc7.

In summary, unless you have a really good reason, it probably isn''t worth it. Ten times slower isn''t really that bad (depending on your compilers implementation and how often you use it). At the same time, it certainly is worth watching for when doing your profiling.

Share this post


Link to post
Share on other sites
well, i thought of a another imho quite big PRO...
dynamic casting "needs" exception handling, if coding with "style"

if having my own rtti, i do not need exception handling in this case, only a simple if statement...

if u are logable, do log

simple? i think so

Share this post


Link to post
Share on other sites
if(obj.is_logable()) {
//log it

}
else {
//do some default action

}


may be better put on the object with the default being put in the base class.


class base {
virtual void logIt(Log& log) {
//default behaviour

}
};
class derived {
virtual void logIt(Log& log) {
log << whatever;
}
};
Log log;
derived d;
d.logIt(log);


The default may be 'do nothing'

[edited by - petewood on January 26, 2004 8:09:20 AM]

Share this post


Link to post
Share on other sites
He''s saying use virtual functions with default definitions instead of RTTI. He has a point. I can really only see using RTTI when you absolutely need the type itself and have to do interesting things with it (such as downcasting to well-defined interfaces in a loose system).

Share this post


Link to post
Share on other sites
quote:
Original post by antareus
He's saying use virtual functions with default definitions instead of RTTI. He has a point. I can really only see using RTTI when you absolutely need the type itself and have to do interesting things with it (such as downcasting to well-defined interfaces in a loose system).


Well, if you were really worried about it, you could put a protected member in the base class that would store the enumeration of that class. Then switch the base class' enumeration (with a getClassType() method):


switch(pBaseClass.GetType())
{
case TRANSLUCENT_WND:
{
//Render all except the top window

m_Windows.RenderZOrderBackToFrontUntilDepth(1);
break;
}
case SLIDER_WND:
{
//Render all except the top window

m_Windows.RenderZOrderBackToFrontUntilDepth(1);
break;
}
case FATALITY_WND:
{
//Clear Screen for Window's last moments (MKDA)

m_RenderTarget.Clear();
}
defalut: break;
}

m_Windows.CurrentWindow.CloseAnimation(t_time_stamp);


This kinda alludes to the Abstract Factory Pattern.

[edited by - natasdm on January 26, 2004 9:02:41 AM]

Share this post


Link to post
Share on other sites
At this address you can find a paper studying the performance of various c++ idioms, like rtti. Basically, typeid should be constant time, and dynamic_cast proportinal to the inheritance tree.

http://anubis.dkuug.dk/jtc1/sc22/wg21/

Bruno

Share this post


Link to post
Share on other sites