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:
Struct22
is created and intialized.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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With