首页 > 解决方案 > 跨度只有在处理大量数据时才能提高性能?

问题描述

我听说了新的 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#htmlbenchmarking

解决方案


推荐阅读