-
Given the following code on .NET 10 RC1, Win11 x64: using System.Diagnostics;
using System.Runtime.CompilerServices;
var t = new Test();
t.Measurement();
public class Test
{
public void Measurement()
{
long sum = 0;
long beginning = GC.GetTotalAllocatedBytes(true);
for (int i = 0; i < 100; i++)
sum += DoWork();
var allocated = GC.GetTotalAllocatedBytes(true) - beginning;
Console.WriteLine($"Allocated: {allocated}, Sum: {sum}");
}
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public long DoWork()
{
var obj0 = new MyClass();
return obj0.Get();
}
}
public class MyClass
{
private long _a00 = (Stopwatch.GetTimestamp() / 1);
private long _a01 = (Stopwatch.GetTimestamp() / 1);
private long _a02 = (Stopwatch.GetTimestamp() / 1);
private long _a03 = (Stopwatch.GetTimestamp() / 1);
private long _a04 = (Stopwatch.GetTimestamp() / 1);
private long _a05 = (Stopwatch.GetTimestamp() / 1);
private long _a06 = (Stopwatch.GetTimestamp() / 1);
private long _a07 = (Stopwatch.GetTimestamp() / 1);
private long _a08 = (Stopwatch.GetTimestamp() / 1);
private long _a09 = (Stopwatch.GetTimestamp() / 1);
private long _a10 = (Stopwatch.GetTimestamp() / 1);
private long _a11 = (Stopwatch.GetTimestamp() / 1);
private long _a12 = (Stopwatch.GetTimestamp() / 1);
private long _a13 = (Stopwatch.GetTimestamp() / 1);
private long _a14 = (Stopwatch.GetTimestamp() / 1);
private long _a15 = (Stopwatch.GetTimestamp() / 1);
private long _a16 = (Stopwatch.GetTimestamp() / 1);
public long Get() => Stopwatch.GetTimestamp()
+ _a00 + _a01 + _a02 + _a03 + _a04 + _a05 + _a06 + _a07 + _a08 + _a09
+ _a10 + _a11 + _a12 + _a13 + _a14 + _a15 + _a16;
} Prints on my machine: Allocated: 0, Sum: 7139329661393982 When I remove the Allocated: 15200, Sum: 7140731878244270 which indicates it could not stack allocate What drives this behavior? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 5 replies
-
The measurement is not precise. 100 loop is too few and the class is never stack allocated. Increasing loop count to 100000, both approaches are allocating:
|
Beta Was this translation helpful? Give feedback.
-
If the constructor of |
Beta Was this translation helpful? Give feedback.
Your constructor is already too large to get inlined. It's just that you added a
/ 1
to make the JIT think your method can be somewhat "foldable" so that the JIT increases the inline heuristics multiplier (which is used to compute the benefit/cost) by a bit for you. And it happens to make your constructor able to be inlined under the new multiplier value because now the JIT thinks it's more beneficial to inline your constructor.The heuristics change almost every version of .NET so don't rely on the behavior of heuristics.