c# - 跨度只有在处理大量数据时才能提高性能?
问题描述
我听说了新的 Span 并写了一个小示例应用程序来对执行时间进行基准测试。
public class Program
{
private static int _times = 20;
public static void Main(string[] args)
{
var stringResponse = "0123456789";
var byteResponse = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
// Benchmark with byte[] and Array.Copy()
var stopWatch = new Stopwatch();
stopWatch.Start();
ParseByteArray(byteResponse);
stopWatch.Stop();
var byteArrayTime = stopWatch.ElapsedMilliseconds;
// Benchmark with Span<byte[]>
stopWatch.Restart();
ParseWithSpanOfByteArray(byteResponse);
stopWatch.Stop();
var spanOfByteArrayTime = stopWatch.ElapsedMilliseconds;
// Benchmark with string and string.SubString()
stopWatch.Restart();
ParseWithString(stringResponse);
stopWatch.Stop();
var stringTime = stopWatch.ElapsedMilliseconds;
// Benchmark with Span<string>
stopWatch.Restart();
ParseWithSpanOfString(stringResponse);
stopWatch.Stop();
var spanStringTime = stopWatch.ElapsedMilliseconds;
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"With byte[] and Array.Copy: {byteArrayTime} ms.");
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"With Span<byte[]> and Slice: {spanOfByteArrayTime} ms.");
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"With string and string.SubString: {stringTime} ms.");
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"With Span<string>: {spanStringTime} ms.");
Console.ReadKey();
}
private static void ParseWithSpanOfString(string response)
{
var result = 0;
var span = response.AsSpan();
for (var i = 0; i < _times; i++)
{
var firstHalf = span.Slice(0, 5);
var secondHalf = span.Slice(5, 5);
result += firstHalf[0];
result += secondHalf[0];
}
Console.WriteLine(result);
}
private static void ParseWithString(string response)
{
var result = 0;
for (var i = 0; i < _times; i++)
{
var firstHalf = response.Substring(0, 5);
var secondHalf = response.Substring(5, 5);
result += firstHalf[0];
result += secondHalf[0];
}
Console.WriteLine(result);
}
private static void ParseByteArray(byte[] response)
{
var result = 0;
for (var i = 0; i < _times; i++)
{
var firstHalf = new byte[5];
var secondHalf = new byte[5];
Array.Copy(response, firstHalf, 5);
Array.Copy(response, 5, secondHalf, 0, 5);
result += firstHalf[0];
result += secondHalf[0];
}
Console.WriteLine(result);
}
private static void ParseWithSpanOfByteArray(Span<byte> response)
{
var result = 0;
for (var i = 0; i < _times; i++)
{
var firstHalf = response.Slice(0, 5);
var secondHalf = response.Slice(5, 5);
result += firstHalf[0];
result += secondHalf[0];
}
Console.WriteLine(result);
}
我发现 Span 承诺的性能提升仅在 _times = 10.000.000 左右开始。我有点失望。
_times = 1000 的结果:
With byte[] and Array.Copy: 3 ms.
With Span<byte[]> and Slice: 22 ms.
With string and string.SubString: 0 ms.
With Span<string>: 3 ms.
_times = 10.000 的结果:
With byte[] and Array.Copy: 4 ms.
With Span<byte[]> and Slice: 23 ms.
With string and string.SubString: 1 ms.
With Span<string>: 3 ms.
_times = 100.000 的结果:
With byte[] and Array.Copy: 19 ms.
With Span<byte[]> and Slice: 26 ms.
With string and string.SubString: 5 ms.
With Span<string>: 6 ms.
_times = 1.000.000 的结果:
With byte[] and Array.Copy: 166 ms.
With Span<byte[]> and Slice: 121 ms.
With string and string.SubString: 72 ms.
With Span<string>: 30 ms.
我是在做错什么,还是在处理少数操作时仍然更喜欢使用 byte[] 和字符串操作?
[编辑] 正如评论中提到的,我必须为我的小应用程序使用发布模式。结果现在有利于 Span。即使 _times = 1:
With byte[] and Array.Copy: 3 ms.
With Span<byte[]> and Slice: 1 ms.
With string and string.SubString: 0 ms.
With Span<string>: 2 ms.
在我的情况下,只有 Span 似乎有点慢......
[编辑] 经过大量评论后,我了解到我的基准测试毫无意义,我需要更多时间才能获得正确的结果。
我现在使用 BenchmarkDotNet 来获得我的结果:
感谢所有的投入!
解决方案
推荐阅读
- c - 如何读入文件但在#之后跳过字符?
- go - 构建项目时意外的目录布局
- angular - 如何在 Angular 中为不同的模板处理未定义的数组?
- xamarin - 无法将 Firebase 服务器密钥添加到 Appcentre / 推送页面不可见
- python - Python:从函数内部命名类型并在函数外部分配变量
- unix-timestamp - Unix 时间,但有闰秒
- maven - AEM Sites:使用 Maven 构建更新设计规则时过滤器更新失败
- c - 将用户输入与文件中的文本进行比较
- android - 如何将 FCM 消息发送到 MainActivity
- powerbi - 净余额 > 0 的不同用户数