Skip to content

Commit 4ab69be

Browse files
authored
Moved stackalloc to separate method. (#2374)
1 parent 7306ee7 commit 4ab69be

File tree

1 file changed

+24
-10
lines changed

1 file changed

+24
-10
lines changed

src/BenchmarkDotNet/Engines/Engine.cs

+24-10
Original file line numberDiff line numberDiff line change
@@ -166,12 +166,9 @@ public Measurement RunIteration(IterationData data)
166166
if (EngineEventSource.Log.IsEnabled())
167167
EngineEventSource.Log.IterationStart(data.IterationMode, data.IterationStage, totalOperations);
168168

169-
Span<byte> stackMemory = randomizeMemory ? stackalloc byte[random.Next(32)] : Span<byte>.Empty;
170-
171-
// Measure
172-
var clock = Clock.Start();
173-
action(invokeCount / unrollFactor);
174-
var clockSpan = clock.GetElapsed();
169+
var clockSpan = randomizeMemory
170+
? MeasureWithRandomMemory(action, invokeCount / unrollFactor)
171+
: Measure(action, invokeCount / unrollFactor);
175172

176173
if (EngineEventSource.Log.IsEnabled())
177174
EngineEventSource.Log.IterationStop(data.IterationMode, data.IterationStage, totalOperations);
@@ -190,9 +187,29 @@ public Measurement RunIteration(IterationData data)
190187
if (measurement.IterationStage == IterationStage.Jitting)
191188
jittingMeasurements.Add(measurement);
192189

190+
return measurement;
191+
}
192+
193+
// This is in a separate method, because stackalloc can affect code alignment,
194+
// resulting in unexpected measurements on some AMD cpus,
195+
// even if the stackalloc branch isn't executed. (#2366)
196+
[MethodImpl(MethodImplOptions.NoInlining)]
197+
private unsafe ClockSpan MeasureWithRandomMemory(Action<long> action, long invokeCount)
198+
{
199+
byte* stackMemory = stackalloc byte[random.Next(32)];
200+
var clockSpan = Measure(action, invokeCount);
193201
Consume(stackMemory);
202+
return clockSpan;
203+
}
194204

195-
return measurement;
205+
[MethodImpl(MethodImplOptions.NoInlining)]
206+
private unsafe void Consume(byte* _) { }
207+
208+
private ClockSpan Measure(Action<long> action, long invokeCount)
209+
{
210+
var clock = Clock.Start();
211+
action(invokeCount);
212+
return clock.GetElapsed();
196213
}
197214

198215
private (GcStats, ThreadingStats, double) GetExtraStats(IterationData data)
@@ -224,9 +241,6 @@ public Measurement RunIteration(IterationData data)
224241
return (gcStats, threadingStats, exceptionsStats.ExceptionsCount / (double)totalOperationsCount);
225242
}
226243

227-
[MethodImpl(MethodImplOptions.NoInlining)]
228-
private void Consume(in Span<byte> _) { }
229-
230244
private void RandomizeManagedHeapMemory()
231245
{
232246
// invoke global cleanup before global setup

0 commit comments

Comments
 (0)