【5min+】閃電光速拳? .NetCore 中的Span

来源:https://www.cnblogs.com/uoyo/archive/2020/01/17/12207148.html
-Advertisement-
Play Games

系列介紹 簡介 【五分鐘的DotNet】是一個利用您的碎片化時間來學習和豐富.net知識的博文系列。它所包含了.net體系中可能會涉及到的方方面面,比如C 的小細節,AspnetCore,微服務中的.net知識等等。 5min+不是超過5分鐘的意思,"+"是知識的增加。so,它是讓您花費5分鐘以下的 ...


系列介紹

簡介

【五分鐘的DotNet】是一個利用您的碎片化時間來學習和豐富.net知識的博文系列。它所包含了.net體系中可能會涉及到的方方面面,比如C#的小細節,AspnetCore,微服務中的.net知識等等。
5min+不是超過5分鐘的意思,"+"是知識的增加。so,它是讓您花費5分鐘以下的時間來提升您的知識儲備量。

正文

在dotnet core2.x之後,引入了一個叫做Span<T>的類型。如果您的項目已經升級到了新版的dotnet core 以及使用C# 7+。您會發現我們曾經使用的許許多多類型都增加了一個擴展方法“AsSpan()”。在Vs中小手一點就會出現:


var s = ("xxx").AsSpan();
var s1 = new byte[10].AsSpan();
//.......more

那麼這個家伙到底是個什麼東西?怎麼用呢?

先來扒一扒它的內部方法:

public readonly ref struct Span<T>
{
    public void Clear();
    public void CopyTo([NullableAttribute(new[] { 0, 1 })] Span<T> destination);
    public void Fill(T value);
    public Enumerator GetEnumerator();
    public Span<T> Slice(int start, int length);
    public T[] ToArray();
    public override string ToString();

    //.....
}

這裡只展示它部分的方法,但是關鍵的一點我們可以看到:它是一個結構性(struct 關鍵字)。

而且!!而且!!! 你沒看錯,它還加了一個ref關鍵字。

所以按照我們在上一篇文章中介紹過的 .net中的棧和堆,我們猜想這種結構類型的數據應該是存放在記憶體棧中,具有很快的訪問速度。而且它擁有了ref關鍵字,證明它具有ref結構體的特點:

  • 不能對 ref struct 裝箱
  • ref struct 類型不能實現介面
  • 不能將 ref struct 聲明為類或常規結構的欄位成員
  • 不能聲明非同步方法中屬於 ref struct 類型的本地變數
  • 無法在迭代器中聲明 ref struct 本地變數
  • 無法捕獲 Lambda 表達式或本地函數中的 ref struct 變數

而且根據它公開的這些方法,我們會發現它有點類似我們常用的幾個基礎類型:string 、 byte[] ……。

所以直覺告訴我們,它應該是一個拿來存放數據的類型。

so,來看看MSDN - Magazine中它的解釋:

System.Span<T> 是在 .NET 中發揮關鍵作用的新值類型。使用它,可以表示任意記憶體的相鄰區域,無論相應記憶體是與托管對象相關聯,還是通過互操作由本機代碼提供,亦或是位於堆棧上。除了具有上述用途外,它仍能確保全全訪問和高性能特性,就像數組一樣。

果不其然,和我們猜想的一樣。那麼它出現的意義是什麼呢? 性能!!!!

而且是超級快的性能。大家都知道以往如果我們想提高數據間的操作效率(比如數據偏移、裁剪等),就只能使用指針來操作記憶體中的數據。這樣雖然一波操作猛如虎,但是寫起來費勁不說,我們還得將傳統的C#代碼設置為不安全代碼,除了添加unsafe關鍵字之外還需要打開項目中執行不安全代碼的選項。

所以,有沒有辦法既不操作指針而又有高性能呢? 好吧,Span大爺來了。

Span在C# 7.x中被引入,所以它的年齡還算比較小,也是因為這些原因。以往的項目可能沒有辦法使用它。

它到底有多快

大家一般都是想直接看東西,所以我寫了一份對比的代碼。功能很簡單,都是截取字元串中的一部分代碼,並且進行多次的迴圈操作。

執行結果我都驚呆了:

x

是的,您沒有看錯。差距不是一般的大。

其實剛開始我以為Span並沒有什麼作用,因為我將數據源(圖中的compareStr)僅僅設置為了幾個單詞。然後對他們進行了1億的迴圈操作,但是最後的結果只有很小的差距,不到百分之30。

後來我想了一下,應該讓數據更貼近現實,於是就將一張圖片轉換為base64然後作為數據源。結果驚呆了,差了接近百倍。而且隨著迴圈次數和對數據源的操作次數的增多,Span和傳統字元串之間的性能差距更大。

傳說中的閃電光速拳到底有多快呢

x

它為什麼這麼快

它與傳統的string操作比起來為什麼會具有這麼快的速度呢? 按照我們之前的一些猜想和msdn所給出的一點信息,我們可以得到以下的結論:

  • 它分配堆棧上而不是在托管堆。
  • 它所創建的數據是記憶體連續的,因此具有更快的遍歷速度。

這些特點和string等原有類型比起來就非常的具有優勢了:原來對string操作涉及到大量的字元串分配和記憶體複製。所以當操作的數據量小的時候還好,但是隨著操作次數和處理數據量的增加之後,這是非常消耗性能的。

x

Span會給我們帶來什麼

那麼,既然它擁有如此高的性能,那麼我們該在什麼地方使用它呢?

這很簡單,如果您以前有對大量字元串進行截取或者處理的地方,一般都可以替換為Span。(為什麼是一般呢

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • import java.io.*; public class test13_6 { public static void main(String []args) throws Exception { FileOutputStream output=null; FileInputStream inpu ...
  • 原文:https://www.jianshu.com/p/e88d3f8151db JWT官網: https://jwt.io/ JWT(Java版)的github地址:https://github.com/jwtk/jjwt 什麼是JWT Json web token (JWT), 是為了在網路應 ...
  • 一、Unittest 單元測試框架,可用於自動化測試用力組織,執行,輸出結果 二、Unittest構成 1. Test Case 2. Test Suite 3. Test Fixture 4. Test Runner (圖片來源於網路) Test Case 一個測試用例是一個獨立的測試單元。它檢查 ...
  • 你可以訪問 "碼雲 樂優商城" 來獲取關於樂優商城的工程代碼。 你可以訪問 "百度雲 樂優優商城" 密碼:ppzy 來獲取關於樂優商城的資料。 一、介紹 樂優商城是一個全品類的電商購物網站(B2C),作為階段性學習工程。 二、軟體架構 三、前端技術選型 1. 基礎的HTML、CSS、JavaScri ...
  • 效果圖 首先是資料庫 /* Navicat MySQL Data Transfer Source Server : xm Source Server Version : 50553 Source Host : localhost:3306 Source Database : test Target ...
  • 一、概述 即時編譯器(Just In Time Compiler),也稱為 JIT 編譯器,它的主要工作是把熱點代碼編譯成與本地平臺相關的機器碼,併進行各種層次的優化,從而提高代碼執行的效率。 那麼什麼是熱點代碼呢?我們知道虛擬機通過解釋器(Interpreter)來執行位元組碼文件,當虛擬機發現某個 ...
  • 用已經搭建好 face_recognition,dlib 環境來進行人臉識別 未搭建好環境請參考:https://www.cnblogs.com/guihua-pingting/p/12201077.html 使用OpenCV 調用攝像頭 import face_recognition import ...
  • 微信公眾號: "Dotnet9" ,網站: "Dotnet9" ,問題或建議: "請網站留言" , 如果對您有所幫助: "歡迎贊賞" 。 C WPF可拖拽的TabControl 閱讀導航 1. 本文背景 2. 代碼實現 3. 本文參考 4. 源碼 1. 本文背景 本文介紹使用第三方開源庫 Draga ...
一周排行
    -Advertisement-
    Play Games
  • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
  • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
  • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
  • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
  • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
  • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
  • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
  • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
  • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
  • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...