C# compiler doesn’t optimize unnecessary casts - c#

A few days back, while writing an answer for this question here on overflow I got a bit surprised by the C# compiler, who wasn’t doing what I expected it to do. Look at the following to code snippets:
First:
object[] array = new object[1];
for (int i = 0; i < 100000; i++)
{
ICollection<object> col = (ICollection<object>)array;
col.Contains(null);
}
Second:
object[] array = new object[1];
for (int i = 0; i < 100000; i++)
{
ICollection<object> col = array;
col.Contains(null);
}
The only difference in code between the two snippets is the cast to ICollection<object>. Because object[] implements the ICollection<object> interface explicitly, I expected the two snippets to compile down to the same IL and be, therefore, identical. However, when running performance tests on them, I noticed the latter to be about 6 times as fast as the former.
After comparing the IL from both snippets, I noticed the both methods were identical, except for a castclass IL instruction in the first snippet.
Surprised by this I now wonder why the C# compiler isn’t ‘smart’ here. Things are never as simple as it seems, so why is the C# compiler a bit naïve here?

My guess is that you have discovered a minor bug in the optimizer. There is all kinds of special-case code in there for arrays. Thanks for bringing it to my attention.

This is a rough guess, but i think it's about the Array's relationship to its generic IEnumerable.
In the .NET Framework version 2.0, the
Array class implements the
System.Collections.Generic.IList,
System.Collections.Generic.ICollection,
and
System.Collections.Generic.IEnumerable
generic interfaces. The
implementations are provided to arrays
at run time, and therefore are not
visible to the documentation build
tools. As a result, the generic
interfaces do not appear in the
declaration syntax for the Array
class, and there are no reference
topics for interface members that are
accessible only by casting an array to
the generic interface type (explicit
interface implementations). The key
thing to be aware of when you cast an
array to one of these interfaces is
that members which add, insert, or
remove elements throw
NotSupportedException.
See MSDN Article.
It's not clear whether this relates to .NET 2.0+, but in this special case it would make perfect sense why the compiler cannot optimize your expression if it only becomes valid at run time.

This doesn't look like more than just a missed opportunity in the compiler to suppress the cast. It will work if you write it like this:
ICollection<object> col = array as ICollection<object>;
which suggests that it gets too conservative because casts can throw exceptions. However, it does work when you cast to the non-generic ICollection. I'd conclude that they simply overlooked it.
There's a bigger optimization issue at work here, the JIT compiler doesn't apply the loop invariant hoisting optimization. It should have re-written the code like this:
object[] array = new object[1];
ICollection<object> col = (ICollection<object>)array;
for (int i = 0; i < 100000; i++)
{
col.Contains(null);
}
Which is a standard optimization in the C/C++ code generator for example. Still, the JIT optimizer can't burn a lot of cycles on the kind of analysis required to discover such possible optimizations. The happy angle on this is that optimized managed code is still quite debuggable. And that there still is a role for the C# programmer to write performant code.

Related

Which is more efficient: myType.GetType() or typeof(MyType)?

Supposing I have a class MyType:
sealed class MyType
{
static Type typeReference = typeof(MyType);
//...
}
Given the following code:
var instance = new MyType();
var type1 = instance.GetType();
var type2 = typeof(MyType);
var type3 = typeReference;
Which of these variable assignments would be the most efficient?
Is performance of GetType() or typeof() concerning enough that it would be beneficial to save off the type in a static field?
typeof(SomeType) is a simple metadata token lookup
GetType() is a virtual call; on the plus side you'll get the derived type if it is a subclass, but on the minus side you'll get the derived class if it is a subclass. If you see what I mean. Additionally, GetType() requires boxing for structs, and doesn't work well for nullable structs.
If you know the type at compiletime, use typeof().
I would go with type2. It doesn't require instantiating an instance to get the type. And it's the most human readable.
The only way to find out is to measure.
The "type1" variant isn't reliable or recommended in any way, since not all types can be constructed. Even worse, it allocates memory that will need to be garbage collector and invokes the object constructors.
For the remaining two options, on my machine "type3" is about twice as fast as "type1" in both debug and release modes. Remember that this is only true for my test - the results may not be true for other processor types, machine types, compilers, or .NET versions.
var sw = System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
{
var y = typeof(Program).ToString();
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
sw.Restart();
for (int i = 0; i < 10000000; i++)
{
var y = typeReference.ToString();
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
That said, it's a bit alarming this question is being asked without a clear requirement. If you noticed a performance problem, you'd likely have already profiled it and know which option was better. That tells me that this is likely premature optimization - you know the saying, "premature optimization is the root of all evil".
Programming code is not measured only by performance. It's also measured by correctness, developer productivity, and maintainability. Increasing the complexity of your code without a strong reason just transfers that cost to somewhere else. What might have been a non-issue has now turned into a serious loss of productivity, both now and for future maintainers of the application.
My recommendation would be to always use the "type1" variant. The measurement code I listed isn't a real world scenario. Caching typeof to a reference variable likely has a ton of side-effects, particularly around the way .NET loads assemblies. Rather than having them load only when needed, it might end up loading them all one every use of the application - turning a theoretical performance optimization into a very real performance problem.
They're rather different.
typeof(MyType) gets a Type object describing the MyType type resolved in compile-type using the ldtoken instruction.
myInstance.GetType() gets the Type object describing the runtime type of the myInstance variable.
Both are intended for different scenarios.
You cannot use typeof(MyType) unless you know the type at the compile-time and have access to it.
You cannot use myInstance.GetType() unless you have an instance of the type.
typeof(MyType) is always more efficient, but you cannot use if you don't see the type at the compile time. You cannot use typeof(MyType) to learn the real runtime type of some variable, because you don't know the type.
Both basically the same. Although typeof can be used on a non-instance class like
typeof(MyClass);
But
MyClass.GetType();
won't even build since you need to have an instance of the class.
Long story short, they both do the same job in different context.

Why Animals[] animals = new Cat[5] compiles, but List<Animal> animals = new List<Cat>() does not?

In his book C# in Depth, Jon Skeet tries to answer the following question:
Why can't I convert List<string> to List<object>?
To explain it, he started with a code-snippet, which includes these two lines:
Animal[] animals = new Cat[5]; //Ok. Compiles fine!
List<Animal> animals = new List<Cat>(); //Compilation error!
As the comments read, the first one compiles fine, but the second one gives compilation error. I didn't really understand the reason. Jon Skeet explained this with saying only that first one compiles because in .NET, arrays are covariant, and second one doesn't compile because generics are not covariant (they're invariant, instead). And furthermore, arrays are covariant in .NET, because arrays are covariant in Java and .NET made it similar to Java.
I'm not completely statisfied with this short-answer. I want to know it in a more detail, with some insight into how compiler handles the difference, and how it generates IL and all.
Also, if I write (taken from the book itself):
Animal[] animals = new Cat[5]; //Ok. Compiles fine!
animals.Add(new Turtle()); //this too compiles fine!
It compiles fine, but fails at runtime. If it has to fail at runtime(which means what I write shouldn't make sense), then why does it compile in the first place? Can I use the instance animals in my code, and which also runs with no runtime error?
Arrays have a weird history with variance in .NET. Proper support for variance was added in the 2.0 version of the CLR - and the language in C# 4.0. Arrays however, have always had a covariant behavior.
Eric Lippert goes into great detail on that in a blog post.
The interesting bit:
Ever since C# 1.0, arrays where the element type is a reference type are covariant. This is perfectly legal:
Animal[] animals = new Giraffe[10];
Since Giraffe is smaller than Animal, and “make an array of” is a covariant operation on types, Giraffe[] is smaller than Animal[], so an instance fits into that variable.
Unfortunately, this particular kind of covariance is broken. It was added to the CLR because Java requires it and the CLR designers wanted to be able to support Java-like languages. We then up and added it to C# because it was in the CLR. This decision was quite controversial at the time and I am not very happy about it, but there’s nothing we can do about it now.
Emphasis added by myself.
If it has to fail at runtime, then why does it compile in the first place?
That's precisely why array covariance is broken. The fact that we allow it means that we allow what should be an error that gets caught at compilation time to be ignored, and instead get caught at runtime.
I'm not completely statisfied with this short-answer. I want to know it in a more detail, with some insight into how compiler handles the difference ...
The compiler handles the difference easily enough. The compiler has a whole bunch of code that determines when one type is compatible with another. Part of that code deals with array-to-array conversions. Part of that code deals with generic-to-generic conversions. The code is a straightforward translation of the relevant lines of the specification.
... and how it generates IL and all.
There is no need to generate any IL whatsoever for a covariant array conversion. Why would we need to generate IL for a conversion between two reference-compatible types? It's like asking what IL we generate for converting a string to an object. A string already is an object, so there's no code generated.
I think Jon Skeet explained it rather well, however if you need that "Ahah" moment consider how generics work.
A generic class like List<> is, for most purposes, treated externally
as a normal class. e.g. when you say List<string>() the compiler says
ListString() (which contains strings) and the compiler can't be smart
enough to convert a ListString to a ListObject by casting the items of
its internal collection.
From reading MSDN blog post, it appears that covariance and contravariance is supported in .NET 4.0 when when working with delegates and interfaces. It mentions Eric's articles also in the second sentence.

Can C# generics be used to elide virtual function calls?

I use both C++ and C# and something that's been on my mind is whether it's possible to use generics in C# to elide virtual function calls on interfaces. Consider the following:
int Foo1(IList<int> list)
{
int sum = 0;
for(int i = 0; i < list.Count; ++i)
sum += list[i];
return sum;
}
int Foo2<T>(T list) where T : IList<int>
{
int sum = 0;
for(int i = 0; i < list.Count; ++i)
sum += list[i];
return sum;
}
/*...*/
var l = new List<int>();
Foo1(l);
Foo2(l);
Inside Foo1, every access to list.Count and list[i] causes a virtual function call. If this were C++ using templates, then in the call to Foo2 the compiler would be able to see that the virtual function call can be elided and inlined because the concrete type is known at template instantiation time.
But does the same apply to C# and generics? When you call Foo2(l), it's known at compile-time that T is a List and therefore that list.Count and list[i] don't need to involve virtual function calls. First of all, would that be a valid optimization that doesn't horribly break something? And if so, is the compiler/JIT smart enough to make this optimization?
This is an interesting question, but unfortunately, your approach to "cheat" the system won't improve the efficiency of your program. If it could, the compiler could do it for us with relative ease!
You are correct that when calling IList<T> through an interface reference, that the methods are dispatched at runtime and therefore cannot be inlined. Therefore the calls to IList<T> methods such as Count and the indexer will be called through the interface.
On the other hand, it is not true that you can achieve any performance advantage (at least not with the current C# compiler and .NET4 CLR), by rewriting it as a generic method.
Why not? First some background. The C# generics work is that the compiler compiles your generic method that has replaceable parameters and then replaces them at run-time with the actual parameters. This you already knew.
But the parameterized version of the method knows no more about the variable types than you and I do at compile time. In this case, all the compiler knows about Foo2 is that list is an IList<int>. We have the same information in the generic Foo2 that we do in the non-generic Foo1.
As a matter of fact, in order to avoid code-bloat, the JIT compiler only produces a single instantiation of the generic method for all reference types. Here is the Microsoft documentation that describes this substitution and instantiation:
If the client specifies a reference type, then the JIT compiler replaces the generic parameters in the server IL with Object, and compiles it into native code. That code will be used in any further request for a reference type instead of a generic type parameter. Note that this way the JIT compiler only reuses actual code. Instances are still allocated according to their size off the managed heap, and there is no casting.
This means that the JIT compiler's version of the method (for reference types) is not type safe but it doesn't matter because the compiler has ensured all type-safety at compile time. But more importantly for your question, there is no avenue to perform inlining and get a performance boost.
Edit: Finally, empirically, I've just done a benchmark of both Foo1 and Foo2 and they yield identical performance results. In other words, Foo2 is not any faster than Foo1.
Let's add an "inlinable" version Foo0 for comparison:
int Foo0(List<int> list)
{
int sum = 0;
for (int i = 0; i < list.Count; ++i)
sum += list[i];
return sum;
}
Here is the performance comparison:
Foo0 = 1719
Foo1 = 7299
Foo2 = 7472
Foo0 = 1671
Foo1 = 7470
Foo2 = 7756
So you can see that Foo0, which can be inlined, is dramatically faster than the other two. You can also see that Foo2 is slightly slower instead of being anywhere near as fast as Foo0.
This actually does work, and does (if the function is not virtual) result in a non-virtual call. The reason is that unlike in C++, CLR generics define, at JIT time, a specific, concrete class for each unique set of generic parameters (indicated via reflection via trailing 1, 2 etc). If the method is virtual, it will result in a virtual call like any concrete, non-virtual, non-generic method.
The thing to remember about .net generics is that given:
Foo<T>;
then
Foo<Int32>
is a valid Type at runtime, separate and distinct from
Foo<String>
, and all virtual and non-virtual methods are treated accordingly. This is the reason why you can create a
List<Vehicle>
and add a Car to it, but you can't create a variable of type
List<Vehicle>
and set its value to an instance of
List<Car>
. They are of different types, but the former has an Add(...) method that takes an argument of Vehicle, a supertype of Car.

C# Dynamic Keyword — Run-time penalty?

Does defining an instance as dynamic in C# mean:
The compiler does not perform compile-time type checking, but run-time checking takes place like it always does for all instances.
The compiler does not perform compile-time type checking, but run-time checking takes place, unlike with any other non-dynamic instances.
Same as 2, and this comes with performance penalty (trivial? potentially significant?).
The question is very confusing.
Does defining an instance as dynamic in C# mean:
By "defining an instance" do you mean "declaring a variable"?
The compiler does not perform compile-time type checking, but run-time checking takes place like it always does for all instances.
What do you mean by "run-time checking like it always does"? What run-time checking did you have in mind? Are you thinking of the checking performed by the IL verifier, or are you thinking of runtime type checks caused by casts, or what?
Perhaps it would be best to simply explain what "dynamic" does.
First off, dynamic is from the perspective of the compiler a type. From the perspective of the CLR, there is no such thing as dynamic; by the time the code actually runs, all instances of "dynamic" have been replaced with "object" in the generated code.
The compiler treats expressions of type dynamic exactly as expressions of type object, except that all operations on the value of that expression are analyzed, compiled and executed at runtime based on the runtime type of the instance. The goal is that the code executed has the same semantics as if the compiler had known the runtime types at compile time.
Your question seems to be about performance.
The best way to answer performance questions is to try it and find out - what you should do if you need hard numbers is to write the code both ways, using dynamic and using known types, and then get out a stopwatch and compare the timings. That's the only way to know.
However, let's consider the performance implications of some operations at an abstract level. Suppose you have:
int x = 123;
int y = 456;
int z = x + y;
Adding two integers takes about a billionth of a second on most hardware these days.
What happens if we make it dynamic?
dynamic x = 123;
dynamic y = 456;
dynamic z = x + y;
Now what does this do at runtime? This boxes 123 and 456 into objects, which allocates memory on the heap and does some copies.
Then it starts up the DLR and asks the DLR "has this code site been compiled once already with the types for x and y being int and int?"
The answer in this case is no. The DLR then starts up a special version of the C# compiler which analyzes the addition expression, performs overload resolution, and spits out an expression tree describing the lambda which adds together two ints. The DLR then compiles that lambda into dynamically generated IL, which the jit compiler then jits. The DLR then caches that compiled state so that the second time you ask, the compiler doesn't have to do all that work over again.
That takes longer than a nanosecond. It takes potentially many thousands of nanoseconds.
Does that answer your questions? I don't really understand what you're asking here but I'm making a best guess.
As far as I know, the answer is 3.
You can do this:
dynamic x = GetMysteriousObject();
x.DoLaundry();
Since the compiler does no type checking on x, it will compile this code, the assumption being that you know what you're doing.
But this means extra run-time checking has to occur: namely, examining x's type, seeing if it has a DoLaundry method accepting no arguments, and executing it.
In other words the above code is sort of like doing this (I'm not saying it's the same, just drawing a comparison):
object x = GetMysteriousObject();
MethodInfo doLaundry = x.GetType().GetMethod(
"DoLaundry",
BindingFlags.Instance | BindingFlags.Public
);
doLaundry.Invoke(x, null);
This is definitely not trivial, though that isn't to say you're going to be able to see a performance issue with your naked eye.
I believe the implementation of dynamic involves some pretty sweet behind-the-scenes caching that gets done for you, so that if you run this code again and x is the same type, it'll run a lot faster.
Don't hold me to that, though. I don't have all that much experience with dynamic; this is merely how I understand it to work.
Declaring a variable as dynamic is similar to declaring it as object. Dynamic simply gets another flag indicating that member resolution gets deferred to run-time.
In terms of the performance penalty - it depends on what the underlying object is. That's the whole point of dynamic objects right? The underlying object can be a Ruby or Python object or it can be a C# object. The DLR will figure out at run-time how to resolve member calls on this object and this resolution method will determine the performance penalty.
Having said that - there definitely is a performance penalty.
That's why we're not simply going to start using dynamic objects all over the place.
I made a simple test: 100000000 assignments to a variable as a dynamic vs. the same number of direct double assignments, something like
int numberOfIterations = 100000000;
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < numberOfIterations; i++)
{
var x = (dynamic)2.87;
}
sw.Stop();
sw.Restart();
for (int i = 0; i < numberOfIterations; i++)
{
double y = 2.87;
}
sw.Stop();
In the first loop (with dynamic) it took some 500ms; in the second one about 200ms. Certainly, the performance loss depends of what you do in your loops, these representing a simplest action possible.
Well, the variable is statically typed to be of the type dynamic but beyond that the compiler doesn't do any checking as far as I know.
Type binding is done at runtime and yes, there's a penalty, but if dynamic is the only option then so what. If you can solve the problem using static typing do so. That being said, the DLR does call site caching which means some of the overhead is reduced as the plumbing can be reused in some cases.
As far i undesrtand dynamic it only bypasses compile time check. resolution of type happens at runtime as it does for all types. so i dont think there is any performance penalty associated with it.

Why do we have generics when we can store things(values and ref) in a ArrayList? [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
What is cool about generics, why use them?
DUPLICATE:
What is cool about generics, why use them?
My basic question is same as title. But I want to know something more that can enlightened me with the world of C# generics.
Thanks!
Aakash
One of the to use a generic list instead of an ArrayList, is that ArrayList accepts objects on any type, and if you intend to store only objects of a given type, this can lead to runtime errors that can't happen with generics.
Example:
var numbers=new ArrayList();
numbers.Add(1);
numbers.Add("abcd"); //This will compile!
int theNumber=(int)numbers[1]; //This will cause an exception
When using a generic list, you ensure that only the desired type is stored in the list:
var numbers=new List<int>();
numbers.Add(1);
numbers.Add("abcd"); //This will NOT compile
A simple explanation.
When you have an list of integers, you just want to make sure that some part of the program adds a string into it. Using generics, you tell the compiler that you decide to only have integers (or whatever type) in the list and it makes sure that you don't break your own law.
You can say, it is another language (and runtime) feature to express your intention in code. This allows the tools to support you.
Further to the answers from Konamiman and Stefan, using generic collections when dealing with value-types will also avoid the cost of boxing/unboxing.
Every time you add a value-type to a non-generic collection it will need to be boxed, and it will then need to be unboxed when you remove it from the collection (assuming that you want to do anything type-specific with it).
ArrayList myList = new ArrayList();
myList.Add(42); // box
myList.Add(DateTime.Now) // box
myList.Add(3.14) // box
int x = (int)myList[0]; // unbox
DateTime y = (DateTime)myList[1]; // unbox
double z = (double)myList[2]; // unbox
As previous posters have said, there is a compile time safety aspect to using generic collections; they can catch some stupid mistakes at compile time (which is better than at runtime).
There are some other reasons to prefer them too, however:
There is a small but occasionally quite relevant performance advantage. If you're dealing with a lot of collection operations in inner loops, the unnecessary type-checks the runtime must perform do add up. If you're computing the sum of integers in an arraylist, expect slower code than the equivalent approach using a List<int> store.
Subtly, but in my mind very relevantly, generic collections aren't only analyzable compile-time, but `coding'-time. This enables intellisense, which is a great feature to have.
Even if you use these collection with values of uncertain type, you'll get the more attractive fail-fast error handling usually.
For instance:
object x = "5";
var intlist = new List<int>();
intlist.Add((int)x); //fails early; compiler requires this cast
//...perhaps much later...
foreach(int num in intlist)...
var arraylist = new ArrayList();
arraylist.Add(x); //this is OK though a cast would be advisable
//...perhaps much later...
foreach(int num in arraylist) ... //fails late
Late failure is harder to debug than early failure since the point when failure is detected is further removed from the original coding error.

Categories

Resources