不太会用Span<T> 看文档上的优点估摸着试试

本次采用最流行而又权威的benchmarkdotnet 基准测试库进行

 

因为确实看文档和网文上关于Span<T>的示例很少,最多就是切string, substring split方面的,具体意思感觉就是多次被调用时如果都在创建临时的数组对象会给gc带来负荷,而这正是Span<T>能解决的

目前我对Span<T>的理解是 在栈上的一块连续内存的安全抽象,当初始化的传入的 数组对象可以看成是该数组对象的一个引用别名。

下面是测试代码:

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace Tester;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;

[SimpleJob(iterationCount: 100)]
public class Test {
  [Params(20)]
  public int len;
  public int[] source;
  [GlobalSetup]
  public void Setup() {
    source = new int[len];
    for (var i = 0; i < len; i++) {
      source[i] = i;
    }
  }
  [Benchmark]
  public int[] GetOddByGeneral() {
    var result = new int[len];
    int _len = 0;
    for (var i = 0; i < len; i++) {
      if (source[i] % 2 == 1) {
        result[i] = source[i];
        _len++;
      }
    }
    return result[0.._len];
  }
  [Benchmark]
  public int[] GetOddBySpan() {
    Span<int> sourceSpan = stackalloc int[len];
    int _len = 0;
    for (var i = 0; i < len; i++) {
      if (source[i] % 2 == 1) {
        sourceSpan[i] = source[i];
        _len++;
      }
    }
    return sourceSpan.Slice(0, _len).ToArray();
  }

}


public class Program {
  static void Main(string[] args) {
    var summary = BenchmarkDotNet.Running.BenchmarkRunner.Run<Test>(
      BenchmarkDotNet.Configs.DefaultConfig.Instance
      .WithSummaryStyle(BenchmarkDotNet.Reports.SummaryStyle.Default.WithMaxParameterColumnWidth(100))
    );
    Console.WriteLine(summary);
  }
}

//结果截图

我不知道我设计这个测试逻辑是否合理,就从测试结果看确实 Span<T>有一点微弱的优势,可能是我代码逻辑不合理造成的,因为在general中我有多余的切片操作这其实是额外的应该避免的。

不过Span<T>方法里也有 slice 先算它们扯平。

 在general方法中 每被调一次就会多一次创建数组的开销 逻辑上说会增加内存消耗,但具体什么情况我不知道。

posted on 2023-11-04 01:03  ProjectDD  阅读(17)  评论(4编辑  收藏  举报