I am in the phase of redesigning the shader system of my engine.
I designed new shiny metaprogrammed shader parameters class that will hold all the parameters (uniforms in GLSL). These parameters are later passed to GLSL. However every shading language can support numerous data types and I don't want to enumerate them in ShaderParameters and use the enum for comparison later. I want user to pass anything he/she wants and let the implementation deal with it. So I thought of a way, what about making a map of boost::any values. These values would hold the uniform value, while the key of the map is uniform's name. In GLSL implementation I would just compare the typeid's of types supported by GLSL to type in boost::any and if they match, I would cast the boost::any and bind it to GLSL.
However I am not quite sure this would perform well. And also it doesn't work with std::vector (I can't detect them or cast them, but if I write their typeid to std::cout - via it's name() method, it shows std::vector<float, std::allocator<float> > when I demangle it. This is really weird and I can't figure out why doesn't it work.
But the main question is: How does typeid(..) comparison operator perform? I need to do approx 30 comparisons in the worst scenario per uniform. Of course I would first check for simple regularly used datatypes (ints, floats, etc.) then later for the advanced ones. Of course I did some tests, it seems to perform rather well, but this is on gcc 4.1.0 and on Linux. I am really curious how does it perform on windows and other platforms aswell.
performance of typeid(..) comparison
Started by kulik, Oct 12 2006 04:28 PM
7 replies to this topic
#1
Posted 12 October 2006 - 04:28 PM
#2
Posted 12 October 2006 - 05:04 PM
See if this link is helpful
http://www.informit....seqNum=120&rl=1
Base on what I know, the typeid() operator can be very expensive. Most of the compiler actually using string comparsion when checking the type id.
I hope it help!
http://www.informit....seqNum=120&rl=1
Base on what I know, the typeid() operator can be very expensive. Most of the compiler actually using string comparsion when checking the type id.
I hope it help!
#3
Posted 12 October 2006 - 05:28 PM
nachilau said:
See if this link is helpful
http://www.informit....seqNum=120&rl=1
Base on what I know, the typeid() operator can be very expensive.
http://www.informit....seqNum=120&rl=1
Base on what I know, the typeid() operator can be very expensive.
code
#include <iostream>
#include <typeinfo>
void compare(const type_info & a, const type_info & ;)
{
bool equals = a == b;
std::cout << "[" << a.name() << "] == [" << b.name() << "]: " << equals << std::endl;
}
struct poly_type { virtual void foo() { } };
struct poly_derived_type : public poly_type { };
struct nonpoly_type { };
int main()
{
int a;
float b;
poly_type c;
poly_derived_type d;
poly_type & e = d;
nonpoly_type f;
compare(typeid(a), typeid(B));
compare(typeid(c), typeid(d));
compare(typeid(c), typeid(e));
compare(typeid(d), typeid(e));
compare(typeid(f), typeid(a));
}
Assembly:
compare(typeid(a), typeid(B)); 004010D1 push offset float `RTTI Type Descriptor' (433064h) 004010D6 push offset int `RTTI Type Descriptor' (433058h) 004010DB call compare (401000h) 004010E0 add esp,8 compare(typeid(c), typeid(d)); 004010E3 push offset poly_derived_type `RTTI Type Descriptor' (433038h) 004010E8 push offset poly_type `RTTI Type Descriptor' (433020h) 004010ED call compare (401000h) 004010F2 add esp,8 compare(typeid(c), typeid(e)); 004010F5 mov ecx,dword ptr [e] 004010F8 push ecx 004010F9 call __RTtypeid (408AB9h) 004010FE add esp,4 00401101 push eax 00401102 push offset poly_type `RTTI Type Descriptor' (433020h) 00401107 call compare (401000h) 0040110C add esp,8 compare(typeid(d), typeid(e)); 0040110F mov edx,dword ptr [e] 00401112 push edx 00401113 call __RTtypeid (408AB9h) 00401118 add esp,4 0040111B push eax 0040111C push offset poly_derived_type `RTTI Type Descriptor' (433038h) 00401121 call compare (401000h) 00401126 add esp,8 compare(typeid(f), typeid(a)); 00401129 push offset int `RTTI Type Descriptor' (433058h) 0040112E push offset nonpoly_type `RTTI Type Descriptor' (433004h) 00401133 call compare (401000h) 00401138 add esp,8
As you can see, for nonpolymorphic types there is already a constructed type_info object ready for use.
As for type_info::operator==():
004089F9 mov eax,dword ptr [esp+4] 004089FD add ecx,9 00408A00 push ecx 00408A01 add eax,9 00408A04 push eax 00408A05 call strcmp (40F0F0h) 00408A0A neg eax 00408A0C pop ecx 00408A0D sbb eax,eax 00408A0F pop ecx 00408A10 inc eax 00408A11 ret 4Indeed a regular string compare.
VC++ 2005 btw.
C++ addict
-
Currently working on: the 3D engine for Tomb Raider.
-
Currently working on: the 3D engine for Tomb Raider.
#4
Posted 12 October 2006 - 07:15 PM
Weird thing is, that from my benches, it proved as approximately 2x - 3x slower than regular enum comparison, and really fast for my purposes. I will investigate further if gcc compares the type_infos with string comparisons too.
#5
Posted 12 October 2006 - 09:42 PM
Would I be wrong in assuming that the 'type_info' returned by two typeid() on the same type would point to the same struct in memory? I don't know if it is standard, but I just tried modifying .oisyns code to use a modified 'compare'
The assembly shows a simple 'cmp', and the output is the same as .oisyns unmodified code.
void compare(const type_info & a, const type_info & b)
{
bool equals = (&a) == (&b);
std::cout << "[" << a.name() << "] == [" << b.name() << "]: " << equals << std::endl;
}
The assembly shows a simple 'cmp', and the output is the same as .oisyns unmodified code.
"Stupid bug! You go squish now!!" - Homer Simpson
#6
Posted 12 October 2006 - 09:50 PM
Yes, that assumption would be wrong. What if the other type_info object came from a dynamic library, for example? The reference would not be the same, but they can still describe the same type.
If the addresses were unique, don't you tink they would have implemented the operator==() function more efficiently than doing a string compare?
. You're code would almost certainly work within the same translation unit, and most probably within the same program as well. But I wouldn't count on this implementation specific behaviour.
If the addresses were unique, don't you tink they would have implemented the operator==() function more efficiently than doing a string compare?
C++ addict
-
Currently working on: the 3D engine for Tomb Raider.
-
Currently working on: the 3D engine for Tomb Raider.
#7
Posted 12 October 2006 - 09:54 PM
Good to know :)
"Stupid bug! You go squish now!!" - Homer Simpson
#8
Posted 13 October 2006 - 08:43 PM
For clarification, under gcc, typeid of the type is instantiated once for a boundary if needed. When comparing, not names but rather the memory locations of the typeids is compared. Several people did notice that, but nobody seemed to have taken care of it.
Because strcmp can be a performance eater, I hash the datatype and compare the hashes then, it seems rather fast.
Because strcmp can be a performance eater, I hash the datatype and compare the hashes then, it seems rather fast.
1 user(s) are reading this topic
0 members, 1 guests, 0 anonymous users












