提问人:Alexander Flesher 提问时间:11/11/2023 更新时间:11/11/2023 访问量:69
在 C# 中,为什么引用引用类型的结构堆栈的推送速度比包含值类型的结构体慢?
In C#, Why Is A Stack of Structs Referencing Reference Types Slower to Push Than Structs Containing Value Types?
问:
如果我有一个堆栈,我会期望一个 mystack。Push() 对于作为结构体的 T 来说,性能大致相同,而对于作为引用类型的 T 来说,性能可能会慢一点。当我对此方案进行基准测试时,包含引用类型的结构的性能似乎比包含值的结构略差。尽管两个结构在内存中的大小相同(64 位)。
基准测试是使用 .NET 6 和 benchmarkdotnet 执行的。
这是我的测试结构;请注意,它们在我的 x64 处理器上的大小应该相同:
public readonly record struct RecStruct(long A);
public readonly record struct PtrStruct(UIntPtr A);
public readonly record struct StructRef(object Ref);
这是我的 benchmarkdotnet 项目类
public class StructPerformance
{
private const int repeats = 1_000_000;
[Benchmark]
public Stack<RecStruct> PushStructWithCap()
{
var stack = new Stack<RecStruct>(repeats);
var strct = new RecStruct(0);
for (int i = 0; i < repeats; i++)
{
stack.Push(strct);
}
return stack;
}
[Benchmark]
public Stack<PtrStruct> PushPtrStructWithCap()
{
var stack = new Stack<PtrStruct>(repeats);
var ptr = new UIntPtr(0);
var strct = new PtrStruct(ptr);
for (int i = 0; i < repeats; i++)
{
stack.Push(strct);
}
return stack;
}
[Benchmark]
public Stack<StructRef> PushStructRefWithCap()
{
var stack = new Stack<StructRef>(repeats);
var obj = new object();
var strct = new StructRef(obj);
for (int i = 0; i < repeats; i++)
{
stack.Push(strct);
}
return stack;
}
[Benchmark]
public Stack<object> PushObjectWithCap()
{
var stack = new Stack<object>(repeats);
var obj = new object();
for (int i = 0; i < repeats; i++)
{
stack.Push(obj);
}
return stack;
}
}
我的基准测试结果很有趣,似乎表明推送包含对象引用的结构与推送对象一样差,而非托管结构的性能更好。
| Method | Mean | Error | StdDev | Median |
|---------------------- |---------:|----------:|----------:|---------:|
| PushStructWithCap | 2.605 ms | 0.0517 ms | 0.1315 ms | 2.583 ms |
| PushPtrStructWithCap | 2.586 ms | 0.0516 ms | 0.1121 ms | 2.558 ms |
| PushStructRefWithCap | 3.245 ms | 0.0643 ms | 0.1207 ms | 3.234 ms |
| PushObjectWithCap | 3.231 ms | 0.0630 ms | 0.1018 ms | 3.217 ms |
对于包含引用的结构,在 Stack.Push() 上额外使用 ~ns/op 的原因是什么?
答: 暂无答案
评论