.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 生态中的支持。


参考资料

.NET/C# 使用 Span 为字符串处理提升性能的更多相关文章

  1. Span<T>和ValueTuple<T>性能是.Net Core非常关键的特性

    Span<T>和ValueTuple<T> 性能是.Net Core一个非常关键的特性,今天我们重点研究一下ValueTuple<T>和Span<T>. ...

  2. paip.提升性能----数据库连接池以及线程池以及对象池

    paip.提升性能----数据库连接池以及线程池以及对象池 目录:数据库连接池c3po,线程池ExecutorService:Jakartacommons-pool对象池 作者Attilax  艾龙, ...

  3. 从零开始写一个武侠冒险游戏-7-用GPU提升性能(2)

    从零开始写一个武侠冒险游戏-7-用GPU提升性能(2) ----把地图处理放在GPU上 作者:FreeBlues 修订记录 2016.06.21 初稿完成. 2016.08.06 增加对 XCode ...

  4. 从零开始写一个武侠冒险游戏-6-用GPU提升性能(1)

    从零开始写一个武侠冒险游戏-6-用GPU提升性能(1) ----把帧动画的实现放在GPU上 作者:FreeBlues 修订记录 2016.06.19 初稿完成. 2016.08.05 增加对 XCod ...

  5. 深入剖析虚拟DOM提升性能(Vue,React);

    I.原始渲染方式(直接操作DOM): 1.state数据: 2.JSX模板: 3.数据 + 模板 相结合,生成真实的DOM来显示: 4.state发生改变: 5.数据 + 模板结合,生成真实的DOM来 ...

  6. [NewLife.XCode]扩展属性(替代多表关联Join提升性能)

    NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netstandard,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示 ...

  7. [NewLife.XCode]高级查询(化繁为简、分页提升性能)

    NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和 ...

  8. 通过jdbc使用PreparedStatement,提升性能,防止sql注入

    为什么要使用PreparedStatement? 一.通过PreparedStatement提升性能 Statement主要用于执行静态SQL语句,即内容固定不变的SQL语句.Statement每执行 ...

  9. SQL Server中使用Check约束提升性能

        在SQL Server中,SQL语句的执行是依赖查询优化器生成的执行计划,而执行计划的好坏直接关乎执行性能.     在查询优化器生成执行计划过程中,需要参考元数据来尽可能生成高效的执行计划, ...

随机推荐

  1. Extjs 分页多选的实现

    Extjs 版本 6.X 单页面的多选,没有任何问题. 直接使用 Grid的配置项进行绑定即可获取: xtype: 'grid', bind: { selection: '{checkedRecord ...

  2. geoserver源码学习与扩展——restAPI访问

    产生这篇文章的想法是在前端通过js调用restAPI时,总是不成功,发送ajax请求时还总是出现类似跨域的问题,后来查找才发现,默认情况下restAPI的访问都需要管理员权限,而通过ajax请求传输用 ...

  3. consul 小結

    Consul Config 使用Git做版本控制的实现 https://segmentfault.com/a/1190000013807641 服务发现 - consul 的介绍.部署和使用 http ...

  4. .Net遍历窗体上控件

    实现遍历窗体上的控件以及找出TextBox控件,代码如下: foreach( Control control in this.Controls ) { if( control is TextBox ) ...

  5. 使用Python操作memcache

    Python连接memcached的库有很多,处于简单以及高效的原则,最终选择了pymemcache, 优点 完全实现了memcached text协议 对于send/recv操作可以配置timeou ...

  6. TIME_WAIT和CLOSE_WAIT

    先看下三次握手四次挥手的状态变化: 通常会遇到下面两种情况: 服务器保持了大量TIME_WAIT状态 服务器保持了大量CLOSE_WAIT状态 因为linux分配给一个用户的文件句柄是有限的,而TIM ...

  7. dpdk CUSE

    As the Userspace I/O HOWTO says For many types of devices, creating a Linux kernel driver is overkil ...

  8. css tips —— 在css中完成国际化

    前提 在日常处理国际化的时候,通常是将key通过类似intl.xx(key)转换为对应环境的文案,可是如果需要在css中加入对应逻辑应该怎么做呢(比如在after的伪元素中显示不同的文案),毕竟在cs ...

  9. 用svg实现不规则形状

    像这种弧形,用纯html和css很难写,但是用svg就简单多了. 可以用作图工具画出一个弧形,然后导成svg格式.在页面中,下面的白块就是div+svg构成 mixin svgCard(...cont ...

  10. 【转】爬取豆瓣电影top250提取电影分类进行数据分析

    一.爬取网页,获取需要内容 我们今天要爬取的是豆瓣电影top250页面如下所示: 我们需要的是里面的电影分类,通过查看源代码观察可以分析出我们需要的东西.直接进入主题吧! 知道我们需要的内容在哪里了, ...