I want to know that which statement is useful from a Performance Point of View whether to use
Object.GetType() == typeof(Type)
or
Object is Type
I want to know that which statement is useful from a Performance Point of View whether to use
Object.GetType() == typeof(Type)
or
Object is Type
The second one:
Object is Type
Tested this 1'000'000'000 times with string
versus int
one gets:
//Release
00:00:18.1428040 //Object.GetType() == typeof(Type)
00:00:03.9791070 //Object is Type
//Debug
00:00:21.3545510 //Object.GetType() == typeof(Type)
00:00:06.2969510 //Object is Type
//Machine specs:
//Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz
//6 GB RAM memory
//Ubuntu 14.04 (OS)
//Runtime: Mono JIT compiler version 3.2.8
//Compiler: Mono dmcs
//Notes: ran these with some background processes, but the difference in time
// is significant enough I guess.
Note: There is a strong semantic difference between the two:
- The equality
==
checks on type equality: in other words, ifA : B
than the equality test will fail forA.GetType() == typeof(B)
whereasA is B
will succeed.- If the object is
null
, it will throw aSystem.NullReferenceException
. In the second case, it will returnfalse
.
This is rather logic from a compiler point-of-view: in the first variant, you query the object for its type. In case that's not really optimized, you do a function call first, that call then says it must return a pointer to the type-table.
In the second case, you omit such calls: the compiler will specialize it by returning the type-code. And if the Type
is known in advance, it can even work out a very fast test for it.
Note furthermore that for some trivial cases, Object is Type
can be optimized: for instance because the compiler can already derive that Object
can't/is always of type Type
.
More advanced
One can also analyze the CIL virtual machine source code, for the first variant, this is:
IL_0000: ldarg.0
IL_0001: callvirt instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
IL_0006: ldtoken [mscorlib]System.Int32
IL_000b: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0010: call bool [mscorlib]System.Type::op_Equality(class [mscorlib]System.Type, class [mscorlib]System.Type)
IL_0015: ret
For the second variant this is:
IL_0000: ldarg.0
IL_0001: isinst [mscorlib]System.Int32
IL_0006: ldnull
IL_0007: cgt.un
IL_0009: ret
(you can of course fill in other types). Now the ldarg.0
and ret
are simply by-products of using a method, so one can ignore them.
What one sees is that in the first variant, one calls the GetType
method explicitly and then calls the ==
operator. Function calls are in general expensive. In the second variant, it checks immediately for isinst
. The code requires less bytes and uses less expensive methods. Although performance of course depends on the implementation of the runtime environment, I think it's rather safe to say the second variant will nearly always beat the first one on performance.
A compiler could probably specialize the first variant such that it runs as efficient as the second, but the Mono C# compiler doesn't seem to do this. Probably none of the available C# compilers will.
© 2022 - 2024 — McMap. All rights reserved.
is
whereas the.GetType() ==
is resolved by performing expensive function calls. – Plausive