为了获得 StringBuilder 操作的性能,我尝试应用对象池。
但是在 net8 和 net7 上池化 StringBuilder 似乎比原始使用要慢。
可能导致问题的原因是什么,基准点网需要任何其他设置吗?
[MemoryDiagnoser]
public class StringBuilderPoolPerformance
{
[Benchmark]
public void WithoutPool()
{
for (int i = 0; i < 10000; i++)
{
var stringBuilder = new StringBuilder();
stringBuilder.Append("Hello World" + i);
}
}
[Benchmark]
public void WithPool()
{
var stringBuilderPool = new
DefaultObjectPoolProvider().CreateStringBuilderPool();
for (var i = 0; i < 10000; i++)
{
var stringBuilder = stringBuilderPool.Get();
stringBuilder.Append("Hello World" + i);
stringBuilderPool.Return(stringBuilder);
}
}
}
Mean
列确实显示Pool变体速度较慢,这是由Pool需要执行的内部管理和锁定引起的。
但是
Gen0
列告诉我们,与常规变体相比,池变体执行的垃圾收集数量还不到一半。
Adam Sitnik(Benchmark.NET 的作者)说“如果 GC 决定在实际工作负载期间(Clock.Start 和 Clock.GetElapsed 之间)收集内存,那么它将包含在最终结果中。”我认为总共大约有 182 次垃圾收集,我们可以有把握地说迭代本身不会触发 GC,因此 GC 所需的时间在统计数据中不可见(它花费在 Benchmark.NET 代码中,而不是在您的代码中) )。如果您将计数从 10000 增加到 1000000 甚至更多,情况可能会发生变化。
所以你的代码现在回答的只是“new SomeClass() 比池化它更快吗,同时忽略 GC?”,答案是“是的,是的”。