How an auto property is compiled? - c#

I am asking this after I have seen some questions and answers about properties and auto properties and how these are represented by the compiler.
From what I understood, an auto-property is represented as a field, with two methods, a getter an a setter. In this case if a field is used, the code to access that field should be faster than the code which accesses a property, because it avoids any suplimentar call to methods. In order to prove this theory I was writing the following code, and please, excuse me for how it looks:
public class A
{
public int Prop { get; set; }
public int Field;
public A()
{
Prop = 1;
Field = 1;
}
}
class Program
{
static void Main(string[] args)
{
List<long> propertyExecutionTimes = new List<long>();
List<long> fieldExecutionTimes = new List<long>();
A a = new A();
int aux;
for (int j = 0; j < 100; j++)
{
var watch = System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
{
aux = a.Prop;
a.Prop = aux;
}
watch.Stop();
propertyExecutionTimes.Add(watch.ElapsedMilliseconds);
watch = System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
{
aux = a.Field;
a.Field = aux;
}
watch.Stop();
fieldExecutionTimes.Add(watch.ElapsedMilliseconds);
}
Console.WriteLine("Property best time: " + propertyExecutionTimes.OrderBy(x => x).First());
Console.WriteLine("Field best time: " + fieldExecutionTimes.OrderBy(x => x).First());
Console.ReadKey();
}
}
It consists of calling 10M times a field, vs calling 10M times a property everthing 10 times, and then it is picked the lowest value from each test. The results with a VS2012 release version were:
Property best time: 96
Field best time: 45
So as expected the results for a field were quite better than a property.
But after this I runned the program without debugger (simply run the .exe file) and as a surprise for me, the times were similar for both using field and a property like this:
Property best time: 20
Field best time: 20
In this case the differences between using a property and a field were none, which makes me consider that they are compiled in this case as the same, or the methods of the property were converted to something similar with inline methods in C++. This made me think I should see how actual getters and setters are working copared to the property, so I have added a pair of getters and setters:
private int _field;
public int Get() { return _field; }
public void Set(int value) { _field = value; }
Similar testing this against a property with a few changes to respect the same behavior:
aux = a.Get();
a.Set(aux);
Gave me this output:
Property best time: 96
Methods best time: 96
With debugger and:
Property best time: 20
Methods best time: 20
Without debugger. These values are the same, so I concluded that auto-properties are getters and setters which are compiled just like fields. Is this a correct conclusion? And finaly, why the field was also faster than a property when the debugger was attached?

These values are the same, so I concluded that auto-properties are getters and setters which are compiled just like fields.
Yes, auto-properties are implemented as a field, and a get and optionally a set accessor for that field.
Is this a correct conclusion?
For the wrong reasons, but yes. :) To accurately see how auto-properties are implemented, don't rely on timing, but create a program or library and open that in a MSIL disassembler. As you've seen, timing results can be misleading.
And finaly, why the field was also faster than a property when the debugger was attached?
When debugging, there are far fewer opportunities for things like inlining, since inlining makes it more difficult to set a break point, to support edit-and-continue, etc. It's mainly inlining that makes property accessors as fast as direct field access.

Related

Why can't readonly field check be optimised out of a loop?

When I have a readonly variable:
public readonly bool myVar = true;
And check it in a code like this:
for(int i = 0; i != 10; i++)
{
if(myVar)
DoStuff();
else
DoOtherStuff();
}
Looking at emitted IL, I can see that the check is performed on each iteration of the loop. I would expect the code above to produce the same IL as this:
if (myVar)
{
for(int i = 0; i != 10; i++)
{
DoStuff();
}
}
else
{
for(int i = 0; i != 10; i++)
{
DoOtherStuff();
}
}
So why isn't the check optimised to the outside of the loop, since the field is readonly and can't be changed between iterations?
Your proposed optimization really is a combination of two individual simpler transformations. First is pulling the member access outside the loop. From
for(int i = 0; i != 10; i++)
{
var localVar = this.memberVar;
if(localVar)
DoStuff();
else
DoOtherStuff();
}
to
var localVar = this.memberVar;
for(int i = 0; i != 10; i++)
{
if(localVar)
DoStuff();
else
DoOtherStuff();
}
The second is interchanging the loop condition with the if condition. From
var localVar = this.memberVar;
for(int i = 0; i != 10; i++)
{
if(localVar)
DoStuff();
else
DoOtherStuff();
}
to
var localVar = this.memberVar;
if (localVar) {
for(int i = 0; i != 10; i++)
DoStuff();
}
else {
for(int i = 0; i != 10; i++)
DoOtherStuff();
}
The first one is influenced by readonly. To do it, the compiler has to prove that memberVar cannot change inside the loop, and readonly guarantees this1 -- even though this loop could be called inside a constructor, and the value of memberVar could be changed in the constructor after the loop ends, it cannot be changed in the loop body -- DoStuff() is not a constructor of the current object, neither is DoOtherStuff(). Reflection does not count, while it may be possible to use Reflection to break invariants, it isn't permitted to do so. Threads do count, see footnote.
The second is a simple transformation but a more difficult decision for the compiler to make, because it's difficult to predict whether it will actually improve performance. Naturally you can look at it separately by doing the first transformation on the code yourself, and seeing what code is generated.
Perhaps a more important consideration is that in .NET, the optimization pass takes place in between MSIL and machine code, not during compilation of C# to IL. So you cannot see what optimizations are being done by looking at the MSIL!
1 Or does it? The .NET memory model is considerably more forgiving than e.g. the C++ model where any data race leads very quickly to undefined behavior unless the object is defined volatile/atomic. What if this loop runs in a worker thread spawned from the object constructor, and after spawning the thread, the constructor goes on (which I'll call the "second half") to change the readonly member? Does the memory model require that change to be seen by the worker thread? What if DoStuff() and the second half of the constructor force memory fences, for example access other members which are volatile, or take a lock? So readonly would only allow the optimization in a single-threaded environment.
Because it can be changed using Reflection:
using System;
using System.Reflection;
public class Program
{
public static void Main()
{
var t = new Test();
var field = typeof(Test).GetField("myVar", BindingFlags.Instance | BindingFlags.Public);
Console.WriteLine(t.myVar); // prints True
field.SetValue(t, false);
Console.WriteLine(t.myVar); // prints False
// Trying to use t.myVar = false or true; <-- does not compile
}
}
public class Test
{
public readonly bool myVar = true;
}
Working Fiddle: https://dotnetfiddle.net/W9UO3m
Note there is no way in which the compile time code optimizer can predict or detect with absolute certainty whether or not such reflection code exists, and if it exists, if it will run or not.
A readonly field can be initialized to different values at different points in the code (multiple constructors). It can't be optimized out because multiple constructors allow for multiple values of the field in question.
Now, if you only had one constructor, with no relevant branching, and therefore only one possible value, ever, for that field, I'd expect more from the optimizer. However, that sort of analysis is one reason that C++ takes much longer to compile than C#, and these sorts of tasks aren't typically delegated to the runtime.
For a clearer explanation:
Note
The readonly keyword is different from the const keyword. A const
field can only be initialized at the declaration of the field. A
readonly field can be assigned multiple times in the field declaration
and in any constructor. Therefore, readonly fields can have different
values depending on the constructor used. Also, while a const field is
a compile-time constant, the readonly field can be used for run-time
constants as in the following example:
See https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/readonly
For your specific case, I'd suggest using const instead of readonly, though admittedly I haven't looked for differences in the generated IL.
Honestly, I'm wondering if it really makes a difference. Any CPU that performs branch prediction and has a halfway-decent cache will likely yield the same performance in either case. (Note that I haven't tested that; it's just a suspicion.)

Why is Delegate created with `Delegate.CreateDelegate` faster than lambda and method delegates?

All this time I've been reading about reflection, everybody is always saying: "reflection is slow", "reflection is slow".
Now I decided to test how slow, and for my surprise, a delegate created with reflection is actually about twice as fast as a delegate created with lambda, and, also surprisingly, about four times faster than delegates taking declared methods.
See the code
This is a custom class whose property get method will be used in the delegates:
#class to test
class SomeClass
{
public SomeClass A { get; set; } //property to be gotten
public static SomeClass GetA(SomeClass c) { return c.A; } //declared getter method
}
These are the three delegates I tested:
PropertyInfo AProp = typeof(SomeClass).GetProperty("A");
//1 - Created with reflection
Func<SomeClass, SomeClass> Getter = (Func<SomeClass, SomeClass>)Delegate.CreateDelegate(typeof(Func<SomeClass, SomeClass>), null, AProp.GetGetMethod());
//2 - Created with a lambda expression
Func<SomeClass, SomeClass> Getter2 = c => c.A;
//3 - Created from a declared method
Func<SomeClass, SomeClass> Getter3 = SomeClass.GetA;
These are the tests:
SomeClass C = new SomeClass();
C.A = new SomeClass(); //test doesn't change whether A is set or null
Stopwatch w;
//reflection delegate
w = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++) { SomeClass b = Getter(C); }
w.Stop(); Console.WriteLine(w.Elapsed);
//lambda delegate
w = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++) { SomeClass b = Getter2(C); }
w.Stop(); Console.WriteLine(w.Elapsed);
//method delegate
w = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++) { SomeClass b = Getter3(C); }
w.Stop(); Console.WriteLine(w.Elapsed);
//no delegate
w = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++) { SomeClass b = C.A; }
w.Stop(); Console.WriteLine(w.Elapsed);
And the results:
I also tried inverting the test order, to see if there was an influence, or if the watches were tricking me somehow, but no, tests are consistent.
EDIT: considering the "release" compilation, as suggested:
Now... I would have expected lambda to be slower
Here's the decompile of that:
Func<SomeClass, SomeClass> Getter = (Func<SomeClass, SomeClass>)Delegate.CreateDelegate(typeof(Func<SomeClass, SomeClass>), null, AProp.GetGetMethod());
Func<SomeClass, SomeClass> arg_51_0;
if ((arg_51_0 = Program.<>c.<>9__12_0) == null)
{
arg_51_0 = (Program.<>c.<>9__12_0 = new Func<SomeClass, SomeClass>(Program.<>c.<>9.<Main>b__12_0));
}
Func<SomeClass, SomeClass> Getter2 = arg_51_0;
Func<SomeClass, SomeClass> Getter3 = new Func<SomeClass, SomeClass>(SomeClass.GetA);
Notice the first survives the compiler almost unchanged, while the second the third are pretty heavily modified.
If I had to hazard a guess:
The first call is taking advance of some kind of sneaky memory management C++/COM tricks used in the Delegate library.
The second is creating a new method and adding a null check before calling it's new method.
While the third is doing something similar to the second but is saving that until runtime, which is my guess as to why still a property call within a new inline method (which I would have expected to get put out into its own compiler created method, similar to the second version, so I'm guessing that part is going to happen at compile time, which would explain why it's time is so ridiculously higher than the first two).
I think the comments around reflection being slow are more targeted to large libraries; and I'd guess you're not seeing it here because the reflected on class, is extremely small, so there's not a lot to reflect over.
EDIT: As I was typing up that last bit I decided to try and slow down the first call by expanding the SomeClass object. I added about 30 new properties and 20 or so new methods. Didn't seem to make a difference. I've heard all the warnings on reflection too, so this is a bit surprising. This post points out there's a cache involved with all this that is probably helping a lot to. If all the method meta data is cached then reflections should be faster than going through the extra methods and checks added by the compiler. Maybe it comes in when you're reflecting over an external class, that's not already loaded/cached. That's a significantly more involved experiment though.

Why are structs slower than classes?

I'm creating a C# console-app. I have some critical paths and thought that creating structs would be faster than creating classes since I would not need garbage collection for structs. In my test however I found the opposite.
In the test below, I create 1000 structs and 1000 classes.
class Program
{
static void Main(string[] args)
{
int iterations = 1000;
Stopwatch sw = new Stopwatch();
sw.Start();
List<Struct22> structures = new List<Struct22>();
for (int i = 0; i < iterations; ++i)
{
structures.Add(new Struct22());
}
sw.Stop();
Console.WriteLine($"Struct creation consumed {sw.ElapsedTicks} ticks");
Stopwatch sw2 = new Stopwatch();
sw2.Start();
List<Class33> classes = new List<Class33>();
for (int i = 0; i < iterations; ++i)
{
classes.Add(new Class33());
}
sw2.Stop();
Console.WriteLine($"Class creation consumed {sw2.ElapsedTicks} ticks");
Console.ReadLine();
}
}
My classe / struct are simple:
class Class33
{
public int Property { get; set; }
public int Field;
public void Method() { }
}
struct Struct22
{
public int Property { get; set; }
public int Field;
public void Method() { }
}
Results (drum roll please...)
Struct creating consuming 3038 ticks
Class creating consuming 404 ticks
So the question is: Why would it take close to 10x the amount of time for a Class than it does for a Struct ?
EDIT. I made the Program "Do something" by just assigning integers to the properties.
static void Main(string[] args)
{
int iterations = 10000000;
Stopwatch sw = new Stopwatch();
sw.Start();
List<Struct22> structures = new List<Struct22>();
for (int i = 0; i < iterations; ++i)
{
Struct22 s = new Struct22()
{
Property = 2,
Field = 3
};
structures.Add(s);
}
sw.Stop();
Console.WriteLine($"Struct creating consuming {sw.ElapsedTicks} ticks");
Stopwatch sw2 = new Stopwatch();
sw2.Start();
List<Class33> classes = new List<Class33>();
for (int i = 0; i < iterations; ++i)
{
Class33 c = new Class33()
{
Property = 2,
Field = 3
};
classes.Add(c);
}
sw2.Stop();
Console.WriteLine($"Class creating consuming {sw2.ElapsedTicks} ticks");
Console.ReadLine();
}
and the result is astounding to me. Classes are still at least 2x but the simple fact of assigning integers had a 20x impact!
Struct creating consuming 903456 ticks
Class creating consuming 4345929 ticks
EDIT: I removed references to Methods so there are no reference types in my Class or Struct:
class Class33
{
public int Property { get; set; }
public int Field;
}
struct Struct22
{
public int Property { get; set; }
public int Field;
}
The performance difference can probably (or at least in part) be explained by a simple example.
For structures.Add(new Struct22()); this is what really happens:
A Struct22 is created and intialized.
The Add method is called, but it receives a copy because the item is a value type.
So calling Add in this case has overhead, incurred by making a new Struct22 and copying all fields and properties into it from the original.
To demonstrate, not focusing on speed but on the fact that copying takes place:
private static void StructDemo()
{
List<Struct22> list = new List<Struct22>();
Struct22 s1 = new Struct22() { Property = 2, Field = 3 }; // #1
list.Add(s1); // This creates copy #2
Struct22 s3 = list[0]; // This creates copy #3
// Change properties:
s1.Property = 777;
// list[0].Property = 888; <-- Compile error, NOT possible
s3.Property = 999;
Console.WriteLine("s1.Property = " + s1.Property);
Console.WriteLine("list[0].Property = " + list[0].Property);
Console.WriteLine("s3.Property = " + s3.Property);
}
This will be the output, proving that both Add() and the use of list[0] caused copies to be made:
s1.Property = 777
list[0].Property = 2
s3.Property = 999
Let this be a reminder that the behaviour of structs can be substantially different compared to objects, and that performance should be just one aspect when deciding what to use.
As commented, deciding on struct vs class has many considerations. I have not seen many people concerned with instantiation as it is usually a very small part of the performance impact based on this descision.
I ran a few tests with your code and found it interesting that as the number of instances increases the struct is faster.
I cant answer your question as it appears that your assertion is not true. Classes do not always instantiate faster than Structs. Everything I have read states the opposite, but your test produces the interesting results you mentioned.
There are tools you can use to really dig in and try to find out why you get the results you do.
10000
Struct creation consumed 2333 ticks
Class creation consumed 1616 ticks
100000
Struct creation consumed 5672 ticks
Class creation consumed 8459 ticks
1000000
Struct creation consumed 73462 ticks
Class creation consumed 221704 ticks
List<T> stores T objects in internal Array.
Each time when the limit of capacity is reached, new double sized internal array is created and all values from old array are copied ...
When you create an empty List and try to populate it 1000 times, internal array recreated and copied about 10 times.
So in Your example classes could create slower, but each time when new array is created, List should copy only references to objects in case of List of Class, and all structure data in case of List of Struct ...
Try to create List with initial capacity initialized, for your code it should be:
new List<Struct22>(1000)
in this case internal array wont be recreated and structure case will work much faster

ObjectListView - Displaying arrays

Suppose I have this code:
public sealed class MyStruct {
// ... snip
public uint[] ItemStatValue { get; set; }
// ... snip
}
// MainForm.cs
// ...
Generator.GenerateColumns(this.ContentListView, structure, true);
ContentListView.SetObjects(_records);
// ...
Is there a way to instruct GenerateColumns to treat each element of the ItemStateValue property as a column on its own, and appropriately name them ? ("Item Stat Value 1", "Item Stat Value 2", etc) Currently, it just calls ToString() on the object, thus returning System.Type.UInt32[]. Not exactly what I'd want.
I'm using http://www.codeproject.com/Articles/16009/A-Much-Easier-to-Use-ListView
Cheers!
No, that is not possible. The OLV uses reflection on the type of the specified item to gather the required information. If you supply an IEnumerable it just looks at the type of the first item.
The Generator has no clue and does not care about the actual instances of your items. Also, it wouldn't make much sense in your proposed case, since the number of elements could differ between each struct.
How many items are going to be in the array? ListViews have a fixed number of columns, i.e. each row has the same number of columns.
If you know there is going to be, say, 20 possible stats, just generate the columns.
const int numberOfColumns = 20;
for (int i = 0; i < numberOfColumns; i++) {
var statIndex = i;
var column = new OLVColumn();
column.Name = "Stat" + i;
column.AspectGetter = delegate(object x) {
MyStruct myStruct = (MyStruct)x;
return statIndex < myStruct.ItemStatValue.Length ? (uint?)myStruct.ItemStatValue[statIndex] : null;
};
column.AspectToStringConverter = delegate(object x) {
uint? value = (uint?)x;
return value.HasValue ? String.Format("Stat value: {0}", value.Value) : String.Empty;
};
this.ContentListView.AllColumns.Add(column);
}
this.ContentListView.RebuildColumns();
Call this after the GenerateColumns()
#Grammarian
So after looking around in the code, I noticed aspect getters for fields. However, Generator.GenerateColumns didn't seem to use its third boolean parameter, named allProperties.
So I threw together this quick code, and sure enough, it worked. It doesn't seem to cause any bug either, which is great.
Here is a gist:
https://gist.github.com/Warpten/c792ad66ad20cc69a918
Note: this also requires that you allow OLVColumnAttribute and OLVIgnoreAttribute to be applied to fields. That's easy enough ;)
Cheers!

Why can't I edit a List member directly in C#

I have a class declared as public class DatumSet : List<datum>, where
public struct datum {
public UInt32[] chan;
public UInt64 sample_number;
public float time;
public UInt32 source_sector;
}
I want to iterate through the List and make some changes. Why does this NOT work
for (int i = 0; i < this.Count; i++) {
this[i].sample_number = startSample;
this[i].time = (float)startSample / _sample_rate;
startSample++;
}
but this DOES work
for (int i = 0; i < this.Count; i++) {
datum d = this[i];
d.sample_number = sampleNumber;
d.time = (float)sampleNumber / _sample_rate;
sampleNumber++;
}
I get the error:
Cannot modify the return value of 'System.Collections.Generic.List.this[int]' because it is not a variable
This is what you get for using a mutable value type :)
Think of an indexer as just like a method call. So this:
this[i].sample_number = startSample;
is like:
GetValue(i).sample_number = startSample;
But because datum is a value type (a struct), the method is returning a copy of the value in the list - so modifying it would do you no good at all.
The compiler is stopping you from making that mistake.
You claim that this works:
for (int i = 0; i < this.Count; i++) {
datum d = this[i];
d.sample_number = sampleNumber;
d.time = (float)sampleNumber / _sample_rate;
sampleNumber++;
}
... but in reality, it does nothing useful. It's equivalent to:
sampleNumber += this.Count;
That's all. It compiles, but that's not the same as it working.
I would suggest that you make all value types immutable; it helps to prevent you from getting into this mess. So either you can keep datum as a value type, and replace the value in the list on each iteration, or you can change it to be a class, and modify the objects via the reference stored in the list.
(Either way, I'd strongly suggest that you start using properties instead of public fields, and start following .NET naming conventions too.)
You're having problems because you are using a struct rather than a class.
When you retrieve a struct from a collection, a copy is made. Your first set of code gives you an error because it detects you're doing something you may not mean to do. You'd actually be editing a copy of the struct rather than the copy in the collection.
The second doesn't produce an error because you explicitly pull the copy out of the collection before editing. This code may compile, but won't modify any of the structs in the collection and thus won't give you the results that you're expecting.

Categories

Resources