खैर, प्रोफाइलर कभी झूठ नहीं बोलता।
चूंकि मेरे पास 18-20 प्रकारों की एक बहुत ही स्थिर पदानुक्रम है जो बहुत ज्यादा नहीं बदल रहा है, मुझे आश्चर्य है कि अगर एक सरल एनुमेड के सदस्य का उपयोग करने से चाल चलेगी और आरटीटीआई की कथित रूप से "उच्च" लागत से बचेंगी। यदि आरटीटीआई वास्तव में यह if
कथन प्रस्तुत करता है, तो मैं अधिक महंगा था। लड़का ओह लड़का, है।
ऐसा लगता है कि RTTI है महंगा, और अधिक एक बराबर की तुलना में महंगा if
बयान या एक साधारण switch
सी ++ में एक आदिम चर पर। तो S.Lott का जवाब पूरी तरह से सही नहीं है, वहाँ है RTTI के लिए अतिरिक्त लागत, और यह है नहीं बस की वजह से एक होने के if
बयान मिश्रण में। इसकी वजह है कि RTTI बहुत महंगा है।
यह परीक्षण Apple LLVM 5.0 कंपाइलर पर किया गया था, जिसमें स्टॉक ऑप्टिमाइज़ेशन (डिफ़ॉल्ट रिलीज़ मोड सेटिंग्स) चालू थे।
इसलिए, मेरे 2 कार्य नीचे हैं, जिनमें से प्रत्येक किसी वस्तु के ठोस प्रकार को या तो 1) आरटीटीआई या 2) एक साधारण स्विच के रूप में दर्शाता है। यह ऐसा 50,000,000 बार करता है। आगे की हलचल के बिना, मैं आपके लिए 50,000,000 रन के सापेक्ष रनटाइम प्रस्तुत करता हूं।
यह सही है, 94% रनटाइम dynamicCasts
लिया । जबकि ब्लॉक ने केवल 3.3% लिया ।regularSwitch
लंबी कहानी छोटी: यदि आप एन- enum
डी टाइप करने के लिए ऊर्जा खर्च कर सकते हैं जैसा कि मैंने नीचे किया था, तो मैं शायद इसकी सिफारिश करूंगा, अगर आपको आरटीटीआई करने की आवश्यकता है और प्रदर्शन सर्वोपरि है। यह केवल एक बार सदस्य की स्थापना करता है ( सभी निर्माणकर्ताओं के माध्यम से इसे प्राप्त करना सुनिश्चित करें ), और बाद में इसे कभी भी लिखना सुनिश्चित न करें।
उस ने कहा, ऐसा करने से आपकी ओओपी प्रथाओं को गड़बड़ नहीं होना चाहिए .. इसका उपयोग केवल तब किया जाता है जब टाइप जानकारी बस उपलब्ध नहीं होती है और आप अपने आप को आरटीटीआई का उपयोग करते हुए पाते हैं।
#include <stdio.h>
#include <vector>
using namespace std;
enum AnimalClassTypeTag
{
TypeAnimal=1,
TypeCat=1<<2,TypeBigCat=1<<3,TypeDog=1<<4
} ;
struct Animal
{
int typeTag ;// really AnimalClassTypeTag, but it will complain at the |= if
// at the |='s if not int
Animal() {
typeTag=TypeAnimal; // start just base Animal.
// subclass ctors will |= in other types
}
virtual ~Animal(){}//make it polymorphic too
} ;
struct Cat : public Animal
{
Cat(){
typeTag|=TypeCat; //bitwise OR in the type
}
} ;
struct BigCat : public Cat
{
BigCat(){
typeTag|=TypeBigCat;
}
} ;
struct Dog : public Animal
{
Dog(){
typeTag|=TypeDog;
}
} ;
typedef unsigned long long ULONGLONG;
void dynamicCasts(vector<Animal*> &zoo, ULONGLONG tests)
{
ULONGLONG animals=0,cats=0,bigcats=0,dogs=0;
for( ULONGLONG i = 0 ; i < tests ; i++ )
{
for( Animal* an : zoo )
{
if( dynamic_cast<Dog*>( an ) )
dogs++;
else if( dynamic_cast<BigCat*>( an ) )
bigcats++;
else if( dynamic_cast<Cat*>( an ) )
cats++;
else //if( dynamic_cast<Animal*>( an ) )
animals++;
}
}
printf( "%lld animals, %lld cats, %lld bigcats, %lld dogs\n", animals,cats,bigcats,dogs ) ;
}
//*NOTE: I changed from switch to if/else if chain
void regularSwitch(vector<Animal*> &zoo, ULONGLONG tests)
{
ULONGLONG animals=0,cats=0,bigcats=0,dogs=0;
for( ULONGLONG i = 0 ; i < tests ; i++ )
{
for( Animal* an : zoo )
{
if( an->typeTag & TypeDog )
dogs++;
else if( an->typeTag & TypeBigCat )
bigcats++;
else if( an->typeTag & TypeCat )
cats++;
else
animals++;
}
}
printf( "%lld animals, %lld cats, %lld bigcats, %lld dogs\n", animals,cats,bigcats,dogs ) ;
}
int main(int argc, const char * argv[])
{
vector<Animal*> zoo ;
zoo.push_back( new Animal ) ;
zoo.push_back( new Cat ) ;
zoo.push_back( new BigCat ) ;
zoo.push_back( new Dog ) ;
ULONGLONG tests=50000000;
dynamicCasts( zoo, tests ) ;
regularSwitch( zoo, tests ) ;
}