After reading this great Is C# a low-level language blog from @mattwar I found an performance issue with the * operator.
There is a difference in performance when using the overloaded operators on a struct with Fields compared to Auto Properties.
Have a look at the following Benchmark.
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System;
namespace ConsoleApp1 {
class Program {
static void Main(string[] args) {
BenchmarkRunner.Run<BM>();
}
}
public class BM {
[Benchmark(Baseline = true)]
public VecWithFields TestVecWithFields() {
var p = new VecWithFields(12f, 5f, 1.5f);
var r = new VecWithFields();
for (int i = 0; i < 100000; i++) {
r = p + r;
//r = p * r;
}
return r;
}
[Benchmark]
public VecWithProperties TestVecWithProperties() {
var p = new VecWithProperties(12f, 5f, 1.5f);
var r = new VecWithProperties(); ;
for (int i = 0; i < 100000; i++) {
r = p + r;
//r = p * r;
}
return r;
}
[Benchmark]
public ReadOnlyVecWithProperties TestReadOnlyVecWithProperties() {
var p = new ReadOnlyVecWithProperties(12f, 5f, 1.5f);
var r = new ReadOnlyVecWithProperties(); ;
for (int i = 0; i < 100000; i++) {
r = p + r;
//r = p * r;
}
return r;
}
[Benchmark]
public VecWithProperties TestVecWithPropertiesNoOperator() {
var p = new VecWithProperties(12f, 5f, 1.5f);
var r = new VecWithProperties(); ;
for (int i = 0; i < 100000; i++) {
r = new VecWithProperties(p.X + r.X, p.Y + r.Y, p.Z + r.Z);
//r = p * r;
//r = new VecWithProperties(p.X * r.X, p.Y * r.Y, p.Z * r.Z);
}
return r;
}
}
public struct VecWithFields {
public float X;
public float Y;
public float Z;
public VecWithFields(float x, float y, float z) {
this.X = x;
this.Y = y;
this.Z = z;
}
public static VecWithFields operator *(VecWithFields q, VecWithFields r) {
return new VecWithFields(q.X * r.X, q.Y * r.Y, q.Z * r.Z);
}
public static VecWithFields operator +(VecWithFields q, VecWithFields r) {
return new VecWithFields(q.X + r.X, q.Y + r.Y, q.Z + r.Z);
}
}
public struct VecWithProperties {
public float X { get; set; }
public float Y { get; set; }
public float Z { get; set; }
public VecWithProperties(float x, float y, float z) {
this.X = x;
this.Y = y;
this.Z = z;
}
public static VecWithProperties operator *(VecWithProperties q, VecWithProperties r) {
return new VecWithProperties(q.X * r.X, q.Y * r.Y, q.Z * r.Z);
}
public static VecWithProperties operator +(VecWithProperties q, VecWithProperties r) {
return new VecWithProperties(q.X + r.X, q.Y + r.Y, q.Z + r.Z);
}
}
public readonly struct ReadOnlyVecWithProperties {
public float X { get; }
public float Y { get; }
public float Z { get; }
public ReadOnlyVecWithProperties(float x, float y, float z) {
this.X = x;
this.Y = y;
this.Z = z;
}
public static ReadOnlyVecWithProperties operator *(ReadOnlyVecWithProperties q, ReadOnlyVecWithProperties r) {
return new ReadOnlyVecWithProperties(q.X * r.X, q.Y * r.Y, q.Z * r.Z);
}
public static ReadOnlyVecWithProperties operator +(ReadOnlyVecWithProperties q, ReadOnlyVecWithProperties r) {
return new ReadOnlyVecWithProperties(q.X + r.X, q.Y + r.Y, q.Z + r.Z);
}
}
}
The TestVecWithProperties() method is almost 5 times slower when using the + opeator. I also tested the * operator and it is more than 3 times slower. The C# 7.2 readonly struct is also slower.
BenchmarkDotNet=v0.11.4, OS=Windows 10.0.18348
Intel Core i7-2640M CPU 2.80GHz (Sandy Bridge), 1 CPU, 4 logical and 2 physical cores
.NET Core SDK=2.2.200
[Host] : .NET Core 2.2.2 (CoreCLR 4.6.27317.07, CoreFX 4.6.27318.02), 64bit RyuJIT
DefaultJob : .NET Core 2.2.2 (CoreCLR 4.6.27317.07, CoreFX 4.6.27318.02), 64bit RyuJIT
| Method | Mean | Error | StdDev | Ratio | RatioSD |
|-------------------------------- |----------:|----------:|----------:|------:|--------:|
| TestVecWithFields | 95.46 us | 1.0436 us | 0.9251 us | 1.00 | 0.00 |
| TestVecWithProperties | 465.63 us | 7.7676 us | 6.8857 us | 4.88 | 0.09 |
| TestReadOnlyVecWithProperties | 463.03 us | 4.7100 us | 3.9331 us | 4.85 | 0.07 |
| TestVecWithPropertiesNoOperator | 93.72 us | 0.8890 us | 0.8316 us | 0.98 | 0.02 |
Is this by design or a bug?
category:cq
theme:inlining
skill-level:expert
cost:large
After reading this great Is C# a low-level language blog from @mattwar I found an performance issue with the * operator.
There is a difference in performance when using the overloaded operators on a struct with Fields compared to Auto Properties.
Have a look at the following Benchmark.
The TestVecWithProperties() method is almost 5 times slower when using the + opeator. I also tested the * operator and it is more than 3 times slower. The C# 7.2 readonly struct is also slower.
Is this by design or a bug?
category:cq
theme:inlining
skill-level:expert
cost:large