.NET/C# 使用 Span 为字符串处理提升性能
.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 中有限的字符串性能提升
缺少了 StringBuilder 对 ReadOnlySpan<char> 的支持,广泛使用的字符串拼接功能便没有办法获得 Span 的支持。
不过,System.Memory 中提供了其它有限的字符串处理支持,来源于以下两个类型:
System.Buffers.Text.Utf8ParserSystem.Buffers.Text.Utf8Formatter
前者提供从 ReadOnlySpan<char> 到 Int32、Double、DateTime、Guid 等类型的解析,后者提供相反的转换。
期待 Microsoft 在未来版本的 System.Memory 库中提供对字符串拼接在低版本 .NET 生态中的支持。
参考资料
- Welcome to C# 7.2 and Span - .NET Blog
- C# 7.2: Understanding Span - Connect(); 2017 - Channel 9
- C# Span 入门
.NET/C# 使用 Span 为字符串处理提升性能的更多相关文章
- Span<T>和ValueTuple<T>性能是.Net Core非常关键的特性
Span<T>和ValueTuple<T> 性能是.Net Core一个非常关键的特性,今天我们重点研究一下ValueTuple<T>和Span<T>. ...
- paip.提升性能----数据库连接池以及线程池以及对象池
paip.提升性能----数据库连接池以及线程池以及对象池 目录:数据库连接池c3po,线程池ExecutorService:Jakartacommons-pool对象池 作者Attilax 艾龙, ...
- 从零开始写一个武侠冒险游戏-7-用GPU提升性能(2)
从零开始写一个武侠冒险游戏-7-用GPU提升性能(2) ----把地图处理放在GPU上 作者:FreeBlues 修订记录 2016.06.21 初稿完成. 2016.08.06 增加对 XCode ...
- 从零开始写一个武侠冒险游戏-6-用GPU提升性能(1)
从零开始写一个武侠冒险游戏-6-用GPU提升性能(1) ----把帧动画的实现放在GPU上 作者:FreeBlues 修订记录 2016.06.19 初稿完成. 2016.08.05 增加对 XCod ...
- 深入剖析虚拟DOM提升性能(Vue,React);
I.原始渲染方式(直接操作DOM): 1.state数据: 2.JSX模板: 3.数据 + 模板 相结合,生成真实的DOM来显示: 4.state发生改变: 5.数据 + 模板结合,生成真实的DOM来 ...
- [NewLife.XCode]扩展属性(替代多表关联Join提升性能)
NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netstandard,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示 ...
- [NewLife.XCode]高级查询(化繁为简、分页提升性能)
NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和 ...
- 通过jdbc使用PreparedStatement,提升性能,防止sql注入
为什么要使用PreparedStatement? 一.通过PreparedStatement提升性能 Statement主要用于执行静态SQL语句,即内容固定不变的SQL语句.Statement每执行 ...
- SQL Server中使用Check约束提升性能
在SQL Server中,SQL语句的执行是依赖查询优化器生成的执行计划,而执行计划的好坏直接关乎执行性能. 在查询优化器生成执行计划过程中,需要参考元数据来尽可能生成高效的执行计划, ...
随机推荐
- java_zlib_资料
1.网页资料 1.1.http://bbs.csdn.net/topics/190020986 1.2. http://cdn.verydemo.com/demo_c89_i166794.html h ...
- php redis 秒杀demo
$redis = new Redis(); $redis->connect("127.0.0.1", "6379"); $redis->select ...
- int数组的下标为n
int 类型的数组 先定义int n = 5: 定义int a[n] = {0}; 编译怎么不通过啊?n必须为常量如果想实现你说的,应该用宏#define n 5int a[n]={0};这样就可以了 ...
- 1-17-Linux中计划任务与日志的管理
本节所讲内容: 1-1 Linux中的计划任务 1-1-1 at计划任务的使用 1-1-2 cron 计划任务的使用 1-1 Linux服务器的日志管理 1-1-1 日志的种类和记录的方式 1-1-2 ...
- RabbitMQ其他(八)
1 RabbitMQ消息队列的小伙伴: ProtoBuf(Google Protocol Buffer) 什么是ProtoBuf? 一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序 ...
- js中的执行环境及作用域
最近在面试时被问到了对作用域链的理解,感觉当时回答的不是很好,今天就来说说js中的作用域链吧. 首先来说说js中的执行环境,所谓执行环境(有时也称环境)它是JavaScript中最为重要的一个概念.执 ...
- Upgrade Bash on Ubuntu from 14.04 to 16.04
过程 1 sudo -S apt-mark hold sudo sudo -S apt-mark hold procps sudo -S apt-mark hold strace 2 sudo do- ...
- MySQL小误区:关于set global sql_slave_skip_counter=N 命令的一些点
背景知识1: 在主从库维护中,有时候需要跳过某个无法执行的命令,需要在slave处于stop状态下,执行 set global sql_slave_skip_counter=N以跳过命令.常用 ...
- shell脚本中四则运算
方法一: (()) ##在括号里面可以直接对变量进行操作 例如:vim test.sh 方法二: let ##let后面加要操作的运算 例如: 方法三: expr ...
- TCP 初步认识
TCP连接的建立---三次握手 第一次握手:客户端TCP首先给服务器端TCP发送一个特殊的TCP数据段. 该数据段不包含应用层数据,并将头部中的SYN位设置为1,所以该数据段被称为SYN数据段. 另外 ...