日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

Span 在網絡編程中可以提供高性能的內存訪問和數據處理能力

來源: 責編: 時間:2024-05-16 17:45:01 166觀看
導讀`Span<T>` 是 .NET Core 2.1 引入的一個新類型,它提供任意內存的連續區域的類型安全和內存安全表示形式。`Span<T>` 可以與任意的值類型或引用類型進行關聯,包括原始內存指針、數組、堆上對象等。通過 `Span<T>`,我們可

IH728資訊網——每日最新資訊28at.com

`Span<T>` 是 .NET Core 2.1 引入的一個新類型,它提供任意內存的連續區域的類型安全和內存安全表示形式。`Span<T>` 可以與任意的值類型或引用類型進行關聯,包括原始內存指針、數組、堆上對象等。通過 `Span<T>`,我們可以對這些數據結構進行高效的讀取和寫入操作,而無需進行拷貝或者分配額外的內存。IH728資訊網——每日最新資訊28at.com

在 .NET 中,許多常見的數據類型,如 `string`、`array` 等,都是引用類型,它們本身并不包含實際的數據,而是在堆上分配了一塊內存來存儲數據,然后將其地址傳遞給變量。這種設計在很多情況下非常方便,但也會帶來一些性能上的問題,比如頻繁的內存分配和釋放、GC 壓力等。`Span<T>` 的出現為解決這些問題提供了一種新的方式。IH728資訊網——每日最新資訊28at.com

使用 `Span<T>`,我們可以盡可能地避免進行內存分配和復制,從而提高代碼的運行效率。同時,由于 `Span<T>` 只是一個“視圖”,它并不會改變原始數據的內容或生命周期,因此也非常安全可靠。在 .NET Core 中,許多常見的 API(如網絡、IO、序列化等)都已經開始支持 `Span<T>`,這為我們編寫高性能、低延遲的代碼提供了更多的可能性。IH728資訊網——每日最新資訊28at.com

Span是如何實現的?

通常不需要了解他們正在使用的庫是如何實現的。但是,就 Span<T> 而言,至少對其背后的細節有一個基本的了解是值得的,因為這些細節暗示了其性能和使用限制。IH728資訊網——每日最新資訊28at.com

首先,Span<T> 是一個包含 ref 和長度的值類型,定義大致如下:IH728資訊網——每日最新資訊28at.com

public readonly ref struct Span<T>{  private readonly ref T _pointer;  private readonly int _length;  ...}

引用 T 字段的概念一開始可能很奇怪,事實上,實際上無法在 C# 甚至 MSIL 中聲明引用 T 字段。但 Span<T> 實際上是為在運行時中使用一種特殊的內部類型而編寫的,該類型被視為實時 (JIT) 內部類型,JIT 為其生成等效的 ref T 字段。考慮一個可能更熟悉的 ref 用法:IH728資訊網——每日最新資訊28at.com

public static void AddOne(ref int value) => value += 1;...var values = new int[] { 42, 84, 126 };AddOne(ref values[2]);Assert.Equal(127, values[2]);

此代碼通過引用傳遞數組中的插槽,這樣(撇開優化不談)堆棧上有一個 ref T。Span<T> 中的 ref T 是相同的想法,只是封裝在一個結構中。直接或間接包含此類 ref 的類型稱為類似 ref 的類型,C# 7.2 編譯器允許通過在簽名中使用 ref 結構來聲明此類類似 ref 的類型。IH728資訊網——每日最新資訊28at.com

從這個簡短的描述中,應該清楚兩件事:IH728資訊網——每日最新資訊28at.com

  • Span<T> 的定義方式使操作可以像數組一樣高效:索引到 span 中不需要計算來確定指針的起點及其起始偏移量,因為 ref 字段本身已經封裝了兩者。(相比之下,ArraySegment<T> 具有單獨的偏移字段,因此索引和傳遞的成本更高。
  • Span<T> 作為類似 ref 類型的性質,由于其 ref T 字段而帶來了一些約束。

Span使用注意:

Span<T> 是在堆棧而不是托管堆上分配的 ref 結構 。 Ref 結構類型有許多限制,以確保它們不能提升到托管堆,包括不能裝箱、不能分配給 類型的Objectdynamic變量或任何接口類型,它們不能是引用類型中的字段,也不能跨 await 和 yield 邊界使用。 此外,對和 兩個NotSupportedException方法的 Equals(Object)GetHashCode調用會引發 。IH728資訊網——每日最新資訊28at.com

因為它是僅堆棧類型, Span<T> 不適用于許多需要存儲對堆上的緩沖區的引用的方案。 例如,進行異步方法調用的例程也是如此。 對于此類方案,可以使用互補 System.Memory<T> 和 System.ReadOnlyMemory<T> 類型。IH728資訊網——每日最新資訊28at.com

Span的應用場景

Span<T> 可以看作是一個指向連續內存塊的引用,它可以用于訪問數組、堆棧、堆等數據結構中的連續元素。Span<T> 對象本身不會分配或釋放任何內存,因此它非常適用于內存密集型的應用場景,例如網絡編程、高性能計算等。IH728資訊網——每日最新資訊28at.com

以下是一些 Span<T> 的常見應用場景:IH728資訊網——每日最新資訊28at.com

  • 數組操作:Span<T> 可以用于訪問和操作數組中的元素,包括讀取、修改、排序等操作。與傳統的數組訪問方式相比,Span<T> 更加靈活和高效,可以有效地減少內存分配和拷貝的開銷。
  • 文件操作:Span<T> 可以用于讀取和寫入文件中的二進制數據。通過使用 MemoryMappedFile 和 Span<T>,可以實現高效的文件讀寫操作,并且避免了不必要的內存分配和拷貝。
  • 網絡編程:Span<T> 可以用于訪問網絡數據包中的二進制數據,例如解析 TCP/IP 數據包、HTTP 請求等。通過使用 Span<T>,可以避免數據拷貝和內存分配的開銷,從而提高網絡編程的性能和效率。
  • 高性能計算:Span<T> 可以用于訪問和操作大型數組或矩陣中的元素。通過使用 Span<T>,可以避免不必要的內存分配和拷貝,提高計算速度和效率。

如何使用Span

在 .NET 中,可以通過以下幾種方式來創建 Span<T> 對象:IH728資訊網——每日最新資訊28at.com

直接使用原始內存指針

unsafe{    int[] array = { 1, 2, 3, 4 };    fixed (int* ptr = array)    {        Span<int> span = new Span<int>(ptr, array.Length);        // 對 span 進行操作    }}

在這個例子中,我們首先通過 fixed 關鍵字將 array 數組的地址固定下來,然后使用 new Span<int>(ptr, array.Length) 構造函數創建一個 Span<int> 對象,該對象引用了整個 array 數組。IH728資訊網——每日最新資訊28at.com

使用數組

int[] array = { 1, 2, 3, 4 };Span<int> span = new Span<int>(array);// 對 span 進行操作

在這個例子中,我們直接使用 array 數組創建了一個 Span<int> 對象,該對象引用了整個數組。IH728資訊網——每日最新資訊28at.com

使用數組的一部分

int[] array = { 1, 2, 3, 4 };Span<int> span = new Span<int>(array, 1, 2);// 對 span 進行操作

在這個例子中,我們使用 new Span<int>(array, 1, 2) 構造函數創建了一個 Span<int> 對象,該對象引用了 array 數組的第二個元素和第三個元素。IH728資訊網——每日最新資訊28at.com

使用字符串

string str = "hello world";Span<char> span = str.AsSpan();// 對 span 進行操作

在這個例子中,我們使用 AsSpan 方法將一個字符串轉換為 Span<char> 對象,該對象引用了字符串的所有字符。IH728資訊網——每日最新資訊28at.com

除了上述方式外,還可以使用 Memory<T> 或者 ReadOnlyMemory<T> 類型來創建 Span<T> 對象。Memory<T> 表示一個可變的內存區域,而 ReadOnlyMemory<T> 表示一個不可變的內存區域,它們都可以用來創建 Span<T> 對象。例如:IH728資訊網——每日最新資訊28at.com

int[] array = { 1, 2, 3, 4 };Memory<int> memory = new Memory<int>(array);Span<int> span = memory.Span;// 對 span 進行操作

在這個例子中,我們首先使用 new Memory<int>(array) 構造函數創建了一個 Memory<int> 對象,然后使用 Span 屬性獲取了其對應的 Span<int> 對象。IH728資訊網——每日最新資訊28at.com

使用 Span<T> 可以避免數據拷貝和內存分配的開銷,從而提高網絡編程的性能和效率。一般情況下,網絡數據包的二進制數據往往是連續存儲在內存中的,Span<T> 可以直接引用該內存塊,而不需要進行額外的拷貝操作。IH728資訊網——每日最新資訊28at.com

Span在網絡編程中的應用

使用 Span<T> 解析網絡數據包的一般步驟:IH728資訊網——每日最新資訊28at.com

  • 從網絡中接收到數據:使用網絡編程庫(如Socket)接收網絡數據,將數據存儲在一個字節數組或內存緩沖區中。
  • 創建 Span<T> 對象:通過將字節數組或內存緩沖區傳遞給 Span<T> 的構造函數,創建一個 Span<T> 對象。例如:`Span<byte> dataSpan = new Span<byte>(dataBuffer);`
  • 解析數據:利用 Span<T> 的索引和切片功能,可以方便地訪問和解析二進制數據。可以通過索引獲取特定位置的字節,也可以使用切片操作獲取指定范圍的字節。例如:`byte firstByte = dataSpan[0];` 或 `Span<byte> headerSpan = dataSpan.Slice(0, headerLength);`
  • 處理數據:根據具體的網絡協議,對二進制數據進行解析和處理,提取需要的信息。可以使用 Span<T> 提供的方法或自定義的處理邏輯進行操作。

Span和網絡編程的結合

`Span<T>` 在網絡編程中可以提供高性能的內存訪問和數據處理,從而提升網絡應用程序的效率。下面是幾個使用 `Span<T>` 進行網絡編程的常見場景:IH728資訊網——每日最新資訊28at.com

數據接收和解析:使用 `Socket` 接收到的字節數據可以直接轉換為 `Span<byte>`,避免了額外的內存拷貝操作。然后,可以使用 `Span<T>` 提供的方法對數據進行解析,例如檢查數據包的長度、提取字段值等。IH728資訊網——每日最新資訊28at.com

byte[] buffer = new byte[1024];int bytesRead = socket.Receive(buffer); // 從 Socket 接收數據Span<byte> data = buffer.AsSpan(0, bytesRead);// 解析數據包...`

數據發送:使用 `Span<T>` 可以直接將數據發送到網絡中,而無需將數據復制到新的緩沖區中。這樣可以避免內存拷貝的開銷,提高發送數據的效率。IH728資訊網——每日最新資訊28at.com

byte[] data = GetPacketData(); // 獲取待發送的數據socket.Send(data.AsSpan()); // 直接發送數據

數據處理和轉換:在網絡通信中,涉及到各種數據格式的轉換和處理操作。使用 `Span<T>` 可以方便地對字節數據進行解析、轉換和修改。IH728資訊網——每日最新資訊28at.com

byte[] receivedData = ReceiveDataFromSocket(); // 從 Socket 接收數據// 將接收到的數據轉換為字符串string message = Encoding.UTF8.GetString(receivedData.AsSpan());// 修改數據并發送回去receivedData.AsSpan().Reverse(); // 反轉字節順序SendDataToSocket(receivedData);`

緩沖區池化:在高并發的網絡應用程序中,使用緩沖區池化技術可以避免頻繁的內存分配和釋放操作,提高性能。`Span<T>` 可以與緩沖區池化技術相結合,共享和重用緩沖區,減少內存開銷。IH728資訊網——每日最新資訊28at.com

ArrayPool<byte> bufferPool = ArrayPool<byte>.Shared;byte[] buffer = bufferPool.Rent(1024); // 從緩沖區池中租借一個緩沖區int bytesRead = socket.Receive(buffer); // 從 Socket 接收數據Span<byte> data = buffer.AsSpan(0, bytesRead);// 處理接收到的數據...bufferPool.Return(buffer); // 將緩沖區歸還給緩沖區池`

通過合理地利用 `Span<T>` 的特性和方法,我們可以在網絡編程中實現高效的數據處理和傳輸,提升網絡應用程序的性能和可伸縮性。但需要注意的是,使用 `Span<T>` 時要小心懸掛指針和內存安全問題,確保操作的內存是有效的并且不會被修改。IH728資訊網——每日最新資訊28at.com

使用Socket和Span結合示例

使用 Socket 和 Span<T> 進行網絡數據包解析是一種高效、低內存消耗的方式。下面是一個簡單的示例,演示如何使用這兩個類型進行網絡數據包解析:IH728資訊網——每日最新資訊28at.com

// 假設已經建立了一個 TCP 連接,并且從 Socket 接收到了一段字節數據byte[] buffer = new byte[1024]; // 接收數據的緩沖區int bytesRead = socket.Receive(buffer); // 從 Socket 接收數據Span<byte> data = buffer.AsSpan(0, bytesRead); // 將接收到的字節數據轉換為 Span<byte>// 解析數據包while (data.Length > 0){    // 檢查數據包的長度是否足夠    if (data.Length < sizeof(int))    {        // 數據不完整,等待下一次接收        break;    }    // 讀取數據包的長度    int packetLength = BitConverter.ToInt32(data);        // 檢查數據包是否完整    if (data.Length < packetLength + sizeof(int))    {        // 數據不完整,等待下一次接收        break;    }        // 提取數據包內容    Span<byte> packetData = data.Slice(sizeof(int), packetLength);    // 處理數據包    ProcessPacket(packetData);    // 調整指針,繼續處理剩余數據    data = data.Slice(sizeof(int) + packetLength);}

在上面的示例中,我們首先從 Socket 接收數據,并將接收到的字節數據存儲在一個字節數組中。然后,我們使用 AsSpan 方法將字節數組轉換為 Span<byte>,以便進行高效的數據包解析。IH728資訊網——每日最新資訊28at.com

接下來,我們使用一個循環來處理數據包。在每次循環中,我們首先檢查是否有足夠的數據來讀取數據包的長度。如果數據不完整,我們等待下一次接收。如果有足夠的數據,我們讀取數據包的長度,并檢查是否有足夠的數據來完整解析數據包。如果數據不完整,我們等待下一次接收。IH728資訊網——每日最新資訊28at.com

一旦我們獲得了完整的數據包,我們可以使用 Slice 方法提取數據包的內容,并進行相應的處理操作(例如解析數據、驗證數據、處理數據等)。IH728資訊網——每日最新資訊28at.com

通過使用 Span<T> 和適當的循環邏輯,我們可以高效地解析網絡數據包,減少內存拷貝和數據處理的開銷,從而提高網絡應用程序的性能和效率。IH728資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-88576-0.htmlSpan 在網絡編程中可以提供高性能的內存訪問和數據處理能力

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: Hive SQL底層執行過程詳細剖析

下一篇: 零基礎入門:使用Python pyWinAuto自動化你的Windows任務

標簽:
  • 熱門焦點
  • MIX Fold3包裝盒泄露 新機本月登場

    小米的全新折疊屏旗艦MIX Fold3將于本月發布,近日該機的真機包裝盒在網上泄露。從圖上來看,新的MIX Fold3包裝盒在外觀設計方面延續了之前的方案,變化不大,這也是目前小米旗艦
  • 5月iOS設備好評榜:iPhone 14僅排第43?

    來到新的一月,安兔兔的各個榜單又重新匯總了數據,像安卓陣營的榜單都有著比較大的變動,不過iOS由于設備的更新換代并沒有那么快,所以相對來說變化并不大,特別是iOS好評榜,老款設
  • 《英雄聯盟》夏季賽總決賽今日開打!JDG對陣LNG首發名單來了 Knight:準備三連冠

    8月5日消息,今日17:00,《英雄聯盟》2023LPL夏季賽總決賽將正式開打,由JDG對陣LNG。對兩支隊伍來說,這場比賽不僅要爭奪夏季賽冠軍,更要決定誰才是LPL賽區一
  • 之家push系統迭代之路

    前言在這個信息爆炸的互聯網時代,能夠及時準確獲取信息是當今社會要解決的關鍵問題之一。隨著之家用戶體量和內容規模的不斷增大,傳統的靠"主動拉"獲取信息的方式已不能滿足用
  • 多線程開發帶來的問題與解決方法

    使用多線程主要會帶來以下幾個問題:(一)線程安全問題  線程安全問題指的是在某一線程從開始訪問到結束訪問某一數據期間,該數據被其他的線程所修改,那么對于當前線程而言,該線程
  • Python異步IO編程的進程/線程通信實現

    這篇文章再講3種方式,同時講4中進程間通信的方式一、 Python 中線程間通信的實現方式共享變量共享變量是多個線程可以共同訪問的變量。在Python中,可以使用threading模塊中的L
  • 慕巖炮轟抖音,百合網今何在?

    來源:價值研究所 作者:Hernanderz&ldquo;難道就因為自己的一個產品牛逼了,從客服到總裁,都不愿意正視自己產品和運營上的問題,選擇逃避了嗎?&rdquo;這一番話,出自百合網聯合創
  • 小米汽車電池信息疑似曝光:容量101kWh,支持800V高壓快充

    7月14日消息,今日一名博主在社交媒體發布了一張疑似小米汽車電池信息的照片,顯示該電池包正是寧德時代麒麟電池,容量為101kWh,電壓為726.7V,可以預測小
  • Android 14發布:首批適配機型公布

    5月11日消息,谷歌在今天凌晨舉行了I/O大會,本次發布會谷歌帶來了自家的AI語言模型PaLM 2、谷歌Pixel Fold折疊屏、谷歌Pixel 7a手機,同時發布了Androi
Top 主站蜘蛛池模板: 美姑县| 盐边县| 桂林市| 义马市| 甘肃省| 绥宁县| 永城市| 临西县| 巫溪县| 杭州市| 中方县| 历史| 沭阳县| 洪雅县| 轮台县| 大名县| 西乌珠穆沁旗| 栾城县| 邢台市| 永清县| 于田县| 永宁县| 万源市| 汕头市| 永修县| 昔阳县| 正安县| 济南市| 平潭县| SHOW| 南宁市| 土默特右旗| 杭锦旗| 旺苍县| 宝清县| 安西县| 永吉县| 炉霍县| 施秉县| 乌兰县| 忻州市|