.Net Core中使用ref和Spanamp;lt;Tamp;gt;提高程序性能

一、前言

其实说到ref,很多同学对它已经有所了解,ref是C# 7.0的一个语言特性,它为开发人员提供了返回本地变量引用和值引用的机制。
Span 也是建立在ref语法基础上的一个复杂的数据类型,在文章的后半部分,我会有一个例子说明如何使用它。


二、ref关键字

不论是ref还是out关键,都是一种比较难以理解和操作的语言特性,如C语言中操作指针一样,这样的高级语法总是什么带来一些副作用,但是我不认为这有什么,而且不是每一个C#开发者都要对这些内部运行的机制有着深刻的理解,我觉得不论什么复杂的东西只是为人们提供了一个自由的选择,风险和灵活性永远是不能兼容的。

来看几个例子来说明引用与指针的相同性,当然下面的使用方式早在C# 7.0之前就可以使用了:

public static void IncrementByRef(ref int x){x++;
}public unsafe static void IncrementByPointer(int* x){(*x)++;
}

上面两个函数分别是使用ref和非安全指针来完成参数+1。

int i = 30;
IncrementByRef(ref i);// i = 31unsafe{IncrementByPointer(&i);
}// i = 32

下面是C# 7.0提供的特性:

1.ref locals (引用本地变量)

int i = 42;ref var x = ref i;
x = x + 1;// i = 43

这个例子中为本地 i 变量的引用 x, 当改变x的值时i变量的值也改变了。

2.ref returns (返回值引用)

ref returns是C# 7中一个强大的特性,下面代码是最能体现其特性的,该函数提供了,返回int数组中某一项的引用:

public static ref int GetArrayRef(int[] items, int index) => ref items[index];

通过下标取得数组中的项目的引用,改变引用值时,数组也会随之改变。


三、Span

System.Span 是.Net Core核心的一部分,在 System.Memory.dll 程序集下。目前该特性是独立的,将来可能会集成到CoreFx中;

如何使用呢?在.Net Core 2.0 SDK创建的项目下引用如下NuGet包:

  <ItemGroup><PackageReference Include="System.Memory" Version="4.4.0-preview1-25305-02" /><PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.4.0-preview1-25305-02" /></ItemGroup>

在上面我们看到了使用ref关键字可以提供的类似指针(T*)的操作单一值对象方式。基本上在.NET体系下操作指针都不认为是一件好的事件,当然.NET为我们提供了安全操作单值引用的ref。但是单值只是用户使用“指针”的一小部分需求;对于指针来说,更常见的情况是操作一系列连续的内存空间中的“元素”时。

Span 表示为一个已知长度和类型的连续内存块。许多方面讲它非常类似T[]或ArraySegment ,它提供安全的访问内存区域指针的能力。其实我理解它更将是.NET中操作(void*)指针的抽象,熟悉C/C++开发者应该更明白这意味着什么。

Span 的特点如下:

  • 抽象了所有连续内存空间的类型系统,包括:数组、非托管指针、堆栈指针、fixed或pinned过的托管数据,以及值内部区域的引用

  • 支持CLR标准对象类型和值类型

  • 支持泛型

  • 支持GC,而不像指针需要自己来管理释放

下面来看下Span 的定义,它与ref有着语法和语义上的联系:

public struct Span<T> {  
 ref T _reference;
    int _length;  
      public ref T this[int index] { get {...} }... }
      public struct ReadOnlySpan<T> {  
        ref T _reference;    int _length;    public T this[int index] { get {...} }... }

接下来我会用一个直观的例子来说明Span 的使用场景;我们以字符截取和字符转换(转换为整型)为例:

如有一个字符串string content = "content-length:123",要转换将123转换为整型,通常的做法是先Substring将与数字字符无关的字符串进行截断,转换代码如下:

string content = "content-length:123";
Stopwatch watch1 = new Stopwatch();
watch1.Start();for (int j = 0; j < 100000; j++)
{    int.Parse(content.Substring(15));
}
watch1.Stop();
Console.WriteLine("\tTime Elapsed:\t" + watch1.ElapsedMilliseconds.ToString("N0") + "ms");

为什么使用这个例子呢,这是一个典型的substring的使用场景,每次操作string都会生成新的string对象,当然不光是Substring,在进行int.Parse时重复操作string对象,如果大量操作就会给GC造成压力。

使用Span实现这个算法:

string content = "content-length:123";
ReadOnlySpan<char> span = content.ToCharArray();    
span.Slice(15).ParseToInt();
watch.Start();for (int j = 0; j < 100000; j++)
{    int icb = span.Slice(15).ParseToInt();
}
watch.Stop();
Console.WriteLine("\tTime Elapsed:\t" + watch.ElapsedMilliseconds.ToString("N0") + "ms");

这里将string转换为int的算法利用ReadonlySpan实现,这也是Span 的典型使用场景,官方给的场景也是如些,Span 适用于多次复用操作连续内存的场景。

转换代码如下:

public static class ReadonlySpanxtension{    
public static int ParseToInt(
this ReadOnlySpan<char> rspan)  
 
{Int16 sign = 1;      
 int num = 0;UInt16 index = 0;      
   if (rspan[0].Equals('-')){sign = -1; index = 1;}      
     for (int idx = index; idx < rspan.Length; idx++){        
       char c = rspan[idx];num = (c - '0') + num * 10;}        return num * sign;}}


四、最后

上述两段代码100000次调用的时间如下:

String Substring Convert:        Time Elapsed:   18ms
ReadOnlySpan Convert:        Time Elapsed:   4ms

目前Span 的相关支持还够,它只是最基础架构,之后CoreFx会对很多API使用Span 进行重构和实现。可见.Net Core的性能日后会越来越强大。

原文地址:http://www.cnblogs.com/maxzhang1985/p/6875622.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/325507.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微服务为什么选Spring Cloud

转载自 微服务为什么选Spring Cloud 现如今微服务架构十分流行&#xff0c;而采用微服务构建系统也会带来更清晰的业务划分和可扩展性。同时&#xff0c;支持微服务的技术栈也是多种多样的&#xff0c;本系列文章主要介绍这些技术中的翘楚——Spring Cloud。这是序篇&#x…

压力与动力是否成正比?

昨天在班里测试了下&#xff0c;检测他们数据库学的怎么样&#xff0c;看他们平时在课堂上的互动挺棒。看了下题&#xff0c;不是很难&#xff0c;满怀着愉悦的心情去打印了50份&#xff0c;挨个分发下去&#xff0c;由于我18级那边有课要上&#xff0c;所以这边的考试就辛苦王…

[开源] 基于ABP,Hangfire的开源Sharepoint文件同步解决方案----SuperRocket.SPSync

&#xff08;一&#xff09;项目背景 Sharepoint是微软的一个产品&#xff0c;很多公司都在使用它&#xff0c;也有很多公司以前使用它&#xff0c;现在可能需要移植到别的平台&#xff0c;也可能只是移植其中的文件存储&#xff0c;比如说移植到微软云&#xff0c;或者亚马逊云…

永远不要、不要、不要、不要放弃

Never, never, never, never give up. 永远不要、不要、不要、不要放弃。今天来写一下18级学生们的状态吧&#xff0c;最近主要是解决了1班的三大问题&#xff0c;第一&#xff0c;上机测试问题。第二&#xff0c;周一到四期间学习任务安排问题。第三&#xff0c;学习氛围的进一…

JS的时间定时器

<script>var t null;t setTimeout(time, 1000); //開始运行function time() {clearTimeout(t); //清除定时器dt new Date();var y dt.getFullYear();var mt dt.getMonth() 1;var day dt.getDate();var h dt.getHours(); //获取时var m dt.getMinutes(); //获取分…

微软正式发布XAML Standard与.NET Standard 2.0:现已提供下载

微软在本月早些时候召开的 Build 2017 开发者大会上的披露的 XAML Standard 和 .NET Standard 2.0&#xff0c;现已正式发布。新工具旨在为开发者们带来“基于同一标准的跨平台 XAML 语言结构”&#xff08;基于 UWP 和 Xamarin.Forms&#xff09;&#xff0c;以及基于社区反馈…

Spring Boot 2.X 来临,本文将带你起飞

转载自 Spring Boot 2.X 来临&#xff0c;本文将带你起飞 当前互联网技术盛行&#xff0c;以Spring 框架为主导的Java 互联网技术成了主流&#xff0c;而基于Spring 技术衍生出来的Spring Boot&#xff0c;采用了“约定优于配置”的思想&#xff0c;极大地简化了Spring 框架…

时间胶囊——给未来的留言板

时间胶囊”是一个给未来的留言板&#xff0c;你可以为自己&#xff0c;朋友&#xff0c;爱人&#xff0c;家人&#xff0c;或者任何人留下你现在想对他们说的话、图片&#xff0c;将来某一天&#xff0c;他们将来这里打开“时间胶囊”读到你的留言&#xff01;那么“时间胶囊”…

Echarts五步法加初体验

使用步骤&#xff1a; 引入echarts 插件文件到html页面中准备一个具备大小的DOM容器 <div id"main" style"width: 600px;height:400px;"></div>初始化echarts实例对象 var myChart echarts.init(document.getElementById(main));指定配置项…

深入理解C#:编程技巧总结(一)

以下总结参阅了&#xff1a;MSDN文档、《C#高级编程》、《C#本质论》、前辈们的博客等资料&#xff0c;如有不正确的地方&#xff0c;请帮忙及时指出&#xff01;以免误导&#xff01; 1..实现多态性的两种方式&#xff1a;继承抽象类、实现接口 其实就是协变的应用&#xff…

使用中控指纹采集器开发指纹识别案例V1.0

这两天正好有点琐碎的时间&#xff0c;就将两年前未开发完毕的指纹识别项目翻出来继续写了写。 运行环境&#xff1a;  中控指纹采集器  Win10操作系统  .netframework4.0  Sqlserver2008及以上 源码已经上传到微信公众号【雄雄的小课堂】中&#xff0c;回复“指纹识别…

在CentOS上使用Jexus托管运行 ZKEACMS

ZKEACMS Core 是基于 .net core 开发的&#xff0c;可以在 windows, linux, mac 上跨平台运行&#xff0c;接下来我们来看看如何在 CentOS 上使用Jexus托管运行 ZKEACMS&#xff0c;通常我们在Linux部署ASP.NET Core应用&#xff0c;按照微软的官方文档&#xff0c;我们通常需要…

中控指纹采集器开发指纹识别项目(说明)

历史指纹识别相关开发版本&#xff1a;指纹识别开发1.0&#xff0c;开发时间&#xff1a;2018-01-04 指纹识别开发2.0&#xff0c;开发时间&#xff1a;2018-01-04指纹识别开发3.0&#xff0c;开发时间&#xff1a;2020-01-06可以从时间上看的出来&#xff0c;在2018年1月4日&a…

MSSQL-Scripter,一个新的生成T-SQL脚本的SQL Server命令行工具

这里向大家介绍一个新的生成T-SQL脚本的SQL Server命令行工具&#xff1a;mssql-scripter。它支持在SQL Server、Azure SQL DB以及Azure SQL DW中为数据库生成CREATE和INSERT T-SQL脚本。 Mssql-scripter是一个跨平台的命令行工具&#xff0c;功能等同于SQL Server Management…

用startSmoothScroll实现RecyclerView滚动到指定位置并置顶,含有动画。

RecyclerView滚动到指定位置并置顶 RecyclerView本身提供了几个定位的方法&#xff0c;除了手动滑动的scrollTo&#xff0c;smootScrollTo和scrollBy&#xff0c;smoothScrollBy方法之外&#xff0c;有一个直接滑动到指定位置item的scrollToPosition方法和另一个在此基础上平滑…

重要说明,粉丝必看【java人脸识别说明】

重要通知关于人脸识别简要说明&#xff1a; 源码即日起由免费改为收费。以下是微信收款码&#xff0c;如果有需要可以直接扫码转账即可。&#xff08;注意&#xff0c;源码均为测试好的&#xff0c;故各位在开发的过程中遇到的源码问题不提供任何技术支持。【转账完成之后可以直…

包装类

如果用包装类可以打印出来 <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title></title><script type"text/javascript">var s123;snew String(s);s.hello"nihao";console.log(s.hello);<…

深入理解C#:编程技巧总结(二)

以下总结参阅了&#xff1a;MSDN文档、《C#高级编程》、《C#本质论》、前辈们的博客等资料&#xff0c;如有不正确的地方&#xff0c;请帮忙及时指出&#xff01;以免误导&#xff01; 在上一篇 深入理解C#&#xff1a;编程技巧总结&#xff08;一&#xff09; 中总结了25点&a…

不一样的假期,到底哪里不一样?

目录&#xff1a;1.回访17级同学们&#xff0c;了解同学们目前的工作情况2.和18级同学们聊天&#xff0c;了解假期在家的学习情况3.检查19级同学们提交至小程序内的作业。回忆17级前两天将我带的17级毕业班挨个找了一遍&#xff0c;大致了解了下大家最近的工作情况&#xff0c;…

TensorFlowSharp入门使用C#编写TensorFlow人工智能应用

TensorFlowSharp入门使用C#编写TensorFlow人工智能应用学习。 TensorFlow简单介绍 TensorFlow 是谷歌的第二代机器学习系统&#xff0c;按照谷歌所说&#xff0c;在某些基准测试中&#xff0c;TensorFlow的表现比第一代的DistBelief快了2倍。 TensorFlow 内建深度学习的扩展支…