首頁 後端開發 C#.Net教程 .Net Core中如何使用ref和Span提高程式效能的實作程式碼

.Net Core中如何使用ref和Span提高程式效能的實作程式碼

May 21, 2017 am 11:11 AM

這篇文章主要介紹了.Net Core中使用ref和Span提高程式效能的簡單實作程式碼,需要的朋友可以參考下

一、前言

其實說到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 = 31
unsafe{
 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.

dl# l 程式集下。目前該特性是獨立的,將來可能會整合到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<a href="http://www.php.cn/wiki/57.html" target="_blank"> content = "content-length:123" ,</a>要轉換將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(&#39;-&#39;)){
   sign = -1; index = 1;
  }
  for (int idx = index; idx < rspan.Length; idx++){
   char c = rspan[idx];
   num = (c - &#39;0&#39;) + num * 10;
  }
  return num * sign;
 }
}
登入後複製

四、最后

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

String Substring Convert:
  Time Elapsed: 18ms
ReadOnlySpan Convert:
  Time Elapsed: 4ms
登入後複製

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

以上是.Net Core中如何使用ref和Span提高程式效能的實作程式碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

vue3中怎麼透過ref取得元素節點 vue3中怎麼透過ref取得元素節點 May 16, 2023 pm 12:25 PM

透過ref取得元素節點ref在vue2中可以說簡化js原生的document.getElementById("#id")操作。當然在vue3中也一樣首先,給你想要取得到的元素一個ref屬性然後,再將這個ref物件建立出來,就可以存取到他的值但是。這樣在setup裡邊可以訪問,但是直接打印出來的值為null........由於setup函數的執行時間要先於html標籤的渲染,所以我們不能直接在setup函數中初始化box標籤。在生命週期函數中setup函數在beforeCreat

C#的就業前景如何 C#的就業前景如何 Oct 19, 2023 am 11:02 AM

無論您是初學者還是有經驗的專業人士,掌握C#將為您的職業發展鋪平道路。

分享幾個.NET開源的AI和LLM相關專案框架 分享幾個.NET開源的AI和LLM相關專案框架 May 06, 2024 pm 04:43 PM

當今人工智慧(AI)技術的發展如火如荼,它們在各個領域都展現了巨大的潛力和影響力。今天大姚給大家分享4個.NET開源的AI模型LLM相關的專案框架,希望能為大家提供一些參考。 https://github.com/YSGStudyHards/DotNetGuide/blob/main/docs/DotNet/DotNetProjectPicks.mdSemanticKernelSemanticKernel是一種開源的軟體開發工具包(SDK),旨在將大型語言模型(LLM)如OpenAI、Azure

vue3使用ref的效能警告問題怎麼解決 vue3使用ref的效能警告問題怎麼解決 May 13, 2023 pm 03:10 PM

vue3使用ref的效能警告問題使用ref的效能警告碼如下import{ref,shallowRef}from"vue";importTodoListfrom"./components/TodoList.vue";importRatefrom"./components/Rate.vue";lettabs={ TodoList,Rate}letcurrentTabComponent=ref(TodoList)警告runtime-core.

vue3取得ref實例結合ts的InstanceType問題怎麼解決 vue3取得ref實例結合ts的InstanceType問題怎麼解決 May 20, 2023 pm 10:59 PM

vue3取得ref實例結合ts的InstanceType有時候我們模板引用,但是在使用的時候,ts提示卻不行,沒有提示組件通過defineExpose暴露的方法名稱,雖然這不是很影響,但是可以解決還是可以解決下~import {ref}from'vue'constsayHello=()=>(console.log('我會說hello'))defineExpose({sayHello})然後我們在父級使用,輸入完成MyModalR

vue3+ts中怎麼使用ref與reactive指定型別 vue3+ts中怎麼使用ref與reactive指定型別 May 10, 2023 pm 07:19 PM

ref的基礎特性ref約等於reactive({value:x})ref()可以定義時無參數,第一次賦值任意型,然後不能增加屬性constrefa=ref(6)constrcta=reactive({value:12 })console.log('refa:',refa)//RefImpl{...}console.log('refa:',refa.value)//6console.log('rcta:&#3

vue3中ref綁定dom或元件失敗的原因為何及怎麼解決 vue3中ref綁定dom或元件失敗的原因為何及怎麼解決 May 12, 2023 pm 01:28 PM

vue3ref綁定dom或元件失敗原因分析場景描述在vue3中常用到使用ref綁定元件或dom元素的情況,很多時候,明明使用ref綁定了相關元件,但是經常ref綁定失敗的情況。 ref綁定失敗情況舉例ref綁定失敗的絕大多數情況是,在ref和元件綁定的時候,該元件還未渲染,所以綁定失敗。或是元件剛開始未渲染,ref未綁定,當元件開始渲染,ref也開始綁定,但是ref和元件並未綁定完成,這個時候使用元件相關的方法就會出現問題。 ref綁定的元件使用了v-if,或他的父元件使用了v-if導致頁面

Vue3中的ref和reactive怎麼使用 Vue3中的ref和reactive怎麼使用 May 12, 2023 pm 05:34 PM

一、是什麼ref和reactive是Vue3中用來實現資料響應式的API一般情況下,ref定義基本資料型,reactive定義引用資料型別二、先聊reactivereactive定義引用資料型別(以物件和陣列舉例),它能夠將複雜資料類型的內部屬性或資料項宣告為響應式數據,所以reactive的響應式是深層的,其底層是透過ES6的Proxy來實現資料響應式,相對於Vue2的Object.defineProperty,具有能監聽增刪操作,能監聽物件屬性的變化等優點使用reactive定義物件數

See all articles