Skip to content
欢迎扫码关注公众号

.NET Core 实战 [No.198] 使用 Span<T> 提升处理字符串的性能

Span<T> 用于操作各种 连续分布的内存数据 。可以通过以下来源初始化 Span<T> :

  • 常见的托管数组

    csharp
    Span<char> span = str.ToCharArray();
  • 栈内存中的对象

    csharp
    Span<int> arr = stackalloc [] {1, 2, 3};
  • 本地内存指针

    csharp
    // 从进程的未托管内存中分配 100 字节的内存
    IntPtr native = Marshal.AllocHGlobal(100);
    Span<byte> nativeSpan;
    unsafe
    {
        nativeSpan = new Span<byte>(native.ToPointer(), 100);
    }

Span<T> 支持 GC 功能,不需要显示释放内存。另外 ReadOnlySpan<T> 是其只读版本。

字符串的处理在 C# 和 Java 中都是类似的,每次字符串的修改都会创建一个新的实例,相当耗费资源。

这里通过一个示例,对比一下使用常规方法和使用 Span<T> 方法操作字符串时的性能。
示例功能:截取字符串中的字符 20 并转换为数值。

csharp
string str = "佳佳的博客 - 2020 - www.liujiajia.me";

Stopwatch sw1 = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
{
    int v = int.Parse(str.Substring(9, 2));
}
sw1.Stop();
Console.WriteLine($"常规方法:耗时 {sw1.ElapsedMilliseconds} ms");

Stopwatch sw2 = Stopwatch.StartNew();
ReadOnlySpan<char> span = str.ToCharArray();
for (int i = 0; i < 10000000; i++)
{
    int v = 0;
    var subSpan = span.Slice(9, 2);
    for (int j = 0; j < subSpan.Length; j++)
    {
        char ch = subSpan[j];
        v = (ch - '0') + v * 10;
    }
}
sw2.Stop();
Console.WriteLine($"使用 Span:耗时 {sw2.ElapsedMilliseconds} ms");

使用 str.Substring(9, 2) 方法截取字符串每次都会产生一个新的实例,而使用 span.Slice(9, 2) 则不会。

运行结果如下:


参考:《.NET Core 实战:手把手教你掌握 380 个精彩案例》 -- 周家安 著


Page Layout Max Width

Adjust the exact value of the page width of VitePress layout to adapt to different reading needs and screens.

Adjust the maximum width of the page layout
A ranged slider for user to choose and customize their desired width of the maximum width of the page layout can go.

Content Layout Max Width

Adjust the exact value of the document content width of VitePress layout to adapt to different reading needs and screens.

Adjust the maximum width of the content layout
A ranged slider for user to choose and customize their desired width of the maximum width of the content layout can go.