专栏首页walterlv - 吕毅的博客.NET/C# 使用 Span 为字符串处理提升性能

.NET/C# 使用 Span 为字符串处理提升性能

.NET/C# 使用 Span 为字符串处理提升性能

2018-07-21 16:51

.NET Core 2.1 和 C# 7.2 带来了 Span 的原生支持,原本需要使用不安全代码操作的内存块现在可以使用安全的方式来完成。此前在性能和稳定性上需要有所取舍,而现在可以兼得了。


简单的例子

先来看一个字符串处理时使用 Span<T> 的最简单的例子:

using System;
using System.Text;

namespace Walterlv.Demo.StringSpan
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var text = "https://walterlv.github.io/";
            var nameSpan = text.AsSpan(8, 8);

            var builder = new StringBuilder("Hello ");
            builder.Append(nameSpan);
            builder.AppendLine("!");

            Console.WriteLine(builder.ToString());
        }
    }
}

这个例子是从 https://walterlv.github.io/ 字符串中取出第 8 个字符开始长度为 8 的部分,随后与其它字符串进行拼接。最后,我们得到了拼接的字符串:

这种方式取出字符串替代了 SubString 这种会额外生成临时字符串的方式。如果上述代码发生在较大或较多文本的处理中,那么反复的拼接将生成大量的临时字符串,造成大量 GC 压力;而使用 Span<T> 将不会额外生成任何临时字符串。

语言/框架的支持

然而,只有 .NET Core 2.1 是原生支持字符串的 AsSpan<T> 方法的,.NET Core 2.0、.NET Framework 4.7.2 是不支持的。.NET Core 2.0 可以无视,因为有了 2.1。但 .NET Framework 的低版本却不能无视,因为用户的计算机上通常都是安装低版本的 .NET Framework。

然而我们可以安装 System.Memory,以在低版本的 .NET 中获得字符串扩展方法 AsSpan<T> 的支持。

那么问题来了,低版本的 .NET StringBuilder 中并没有提供 Append(ReadOnlySpan<char>) 方法,于是我们即便使用高性能的方式得到了字符串的一个片段,依然无法将其反复进行拼接。

这真是一个悲伤的故事

低版本 .NET 中有限的字符串性能提升

缺少了 StringBuilderReadOnlySpan<char> 的支持,广泛使用的字符串拼接功能便没有办法获得 Span 的支持。

不过,System.Memory 中提供了其它有限的字符串处理支持,来源于以下两个类型:

  • System.Buffers.Text.Utf8Parser
  • System.Buffers.Text.Utf8Formatter

前者提供从 ReadOnlySpan<char>Int32DoubleDateTimeGuid 等类型的解析,后者提供相反的转换。

期待 Microsoft 在未来版本的 System.Memory 库中提供对字符串拼接在低版本 .NET 生态中的支持。


参考资料

本文会经常更新,请阅读原文: https://walterlv.com/post/improve-string-performance-using-span.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 吕毅 (包含链接: https://walterlv.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 (walter.lv@qq.com)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • .NET 三个字母究竟应该如何大小写?前面的 “.” 什么时候能够去掉?(.NET Standard / dotnet-core / net472)

    发布于 2018-05-28 08:23 更新于 2018-07...

    walterlv
  • 三种方法为 ASP.NET Core 对外服务添加 https 支持(kestrel / frp / nginx)

    虽然使用 Visual Studio 创建 ASP.NET Core 程序的时候可以选择是否添加 https 支持,不过这种方式只添加了 localhost 的...

    walterlv
  • .NET Standard 的管理策略

    2018-07-08 14:28

    walterlv
  • 一次性推荐 GitHub上13款开源项目

    又收集了多个 GitHub 上热门项目,又有哪些新的项目挤进今天的推荐呢,一起来看看?

    Rookie
  • 2019年6月GitHub上最热门的开源项目!

    6月份Github上最热门的开源项目排行出炉,一起来看看本月上榜的开源项目有哪些:

    昱良
  • 刷新:重新发现.NET与未来

    当时的微软对我来说就是神的存在。因为我认识电脑到使用电脑的一切几乎都离不开这家伟大的公司,它就像上帝一样开天辟地,创造万物:Windows、Office、IE这...

    Edison.Ma
  • 刷新:重新发现.NET与未来

    微软在比尔·盖茨手中创立并崛起, 成为PC互联网时代的霸主,很多70,80后都有MVP Edi Wang 的体验<.NET成人礼 | 还记得20年前一起拖过的控...

    梁规晓
  • C#也能做机器学习?基于.NET的AI智能应用市场还是一片“处女地”

    SciSharp 是怎样的一个社区?它是如何构建一个基于 .NET 的机器学习生态?它在做的事情对开发者来说有何意义?本次,AI 科技大本营与 SciSharp...

    AI科技大本营
  • ​(码友推荐)2018-07-03 .NET及相关开发资讯速递

    7.Book Review: ASP.NET Core 2 and Angular 5

    Rector
  • 中国.NET:东莞+长沙.NET俱乐部现场花絮及合肥、苏州、上海等地活动预

    与微软技术的发展历程相似,微软俱乐部的发展经历着沉沉浮浮,曾经随着微软走向封闭与固执,.NET社区年轻一代的声音被忽略,.NET社区后继无人。社区的沉默是可怕的...

    寒树Office与RPA

扫码关注云+社区

领取腾讯云代金券