C#中誰最快:結構還是類?

来源:https://www.cnblogs.com/luquanmingren/archive/2019/07/29/11263161.html
-Advertisement-
Play Games

前言 在記憶體當道的日子里,無論什麼時候都要考慮這些代碼是否會影響程式性能呢? 在現在的世界里,幾乎不會去考慮用了幾百毫秒,可是在特別的場景了,往往這幾百毫米確影響了整個項目的快慢。 通過瞭解這兩者之間的性能差異,希望幫助大家在合適的場景里選擇正確的編碼。 實例 c public class Poin ...


前言

在記憶體當道的日子里,無論什麼時候都要考慮這些代碼是否會影響程式性能呢?
在現在的世界里,幾乎不會去考慮用了幾百毫秒,可是在特別的場景了,往往這幾百毫米確影響了整個項目的快慢。
通過瞭解這兩者之間的性能差異,希望幫助大家在合適的場景里選擇正確的編碼。

實例

public class PointClass
{
    public int X { get; set; }
    public int Y { get; set; }
    public PointClass(int x, int y)
    {
        X = x;
        Y = y;
    }
}

public class PointClassFinalized : PointClass
{
    public PointClassFinalized(int x, int y) : base(x, y)
    {
    }
    ~PointClassFinalized()
    {
        // added a finalizer to slow down the GC

    }
}

public struct PointStruct
{
    public int X { get; set; }
    public int Y { get; set; }
    public PointStruct(int x, int y)
    {
        X = x;
        Y = y;
    }
}

public class StructsTest : PerformanceTest
{
    protected override bool MeasureTestA()
    {
        // access array elements
        var list = new PointClassFinalized[Iterations];
        for (int i = 0; i < Iterations; i++)
        {
            list[i] = new PointClassFinalized(i, i);
        }
        return true;
    }

    protected override bool MeasureTestB()
    {
        // access array elements
        var list = new PointClass[Iterations];
        for (int i = 0; i < Iterations; i++)
        {
            list[i] = new PointClass(i, i);
        }
        return true;
    }

    protected override bool MeasureTestC()
    {
        // access array elements
        var list = new PointStruct[Iterations];
        for (int i = 0; i < Iterations; i++)
        {
            list[i] = new PointStruct(i, i);
        }
        return true;
    }
}

有一個PointClass和一個 PointStruct
,這兩者用於存放X 和Y 兩個變數,而且還有一個 PointClassFinalized

方法 MeasureTestA 創建了100萬個 PointClassFinalized 實例

方法 MeasureTestB 創建了100萬個 PointClass 實例

方法 MeasureTestC 創建了100萬個 PointStruct 實例

您認為哪種方法最快?

MeasureTestBMeasureTestC 這兩個方法的唯一不同在於一個是創建類 一個是創建結構。

MeasureTestC 僅在17毫秒內完成分配並運行,比 MeasureTestB 方法快8.6倍!

為什麼會出現這樣的事情,這裡發生了什麼?

不同的在於結構和類如何存儲在記憶體中。

下麵是 PointClass 實例 記憶體佈局:

該列表是一個局部變數,存放在堆棧中。引用堆上的一組 PointClass實例

PointClass 是一個引用類型,存放在堆上。

該列表僅維護一個數組,指向存儲在堆上 PointClass 實例。

觀察到上圖的黃色箭頭,在堆上引用了很多實例。

數組是一組相同的對象,MeasureTestB 這個方法是將一組相同的對象存放在數組中。

當訪問指定數組元素時,.NET運行時需要檢索對象引用,然後“跟隨”引用以獲取PointClass實例。

當數組元素超出範圍時,.NET垃圾收集器就會開始回收PointClass對象記憶體,在 MeasureTestA 方法中 的PointClassFinalized類 其實增加了額外時間。

.NET Framework在單個線程上運行所有終結器,線程必須在垃圾回收器可以回收記憶體之前依次處理1,000,000個對象。

可以看到MeasureTestAMeasureTestB慢1.7倍。

我們來看看 PointStruct 的記憶體佈局:

結構是值類型,所有 PointStruct 實例都存儲在數組本身中。堆上只有一個對象。

初始化數組,.NET運行庫可以將X和Y值直接寫入數組裡。無需在堆上創建新對象,也不需要引用它。

當訪問指定數組元素時,.NET運行時可以直接檢索結構。

當超出範圍時,.NET垃圾回收器只需要處理單個對象。

總結

我們總要使用結構嗎?要分情況看:

  • 當您存儲超過30-40個位元組的數據時,請使用類。
  • 存儲引用類型時,請使用類。
  • 當您存儲多於幾千個實例時,請使用類。
  • 如果列表是長的生命周期的,請使用類。
  • 在所有其他情況下,使用結構。

相關鏈接:


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

-Advertisement-
Play Games
更多相關文章
  • 4.random 隨機模塊 1. a z:97 ~ 122 A Z :65 ~ 90 5.序列化 1.json 模塊 ​ 兩組4個方法: 1. ​ dumps() :將對象轉(序列化)成字元串 ​ loads() :將字元串轉換(反序列化)成對象 ​ 2. ​ dump() :將對象轉換(序列化)成 ...
  • 1、.NET Remoting概念 1、一種分散式處理方式。從字面意義上看出,他是基於.net平臺的一種遠程對象開發技術,該技術是將遠程電腦中的數據視為分散式對象來進行開發。 2、一種網路通信技術。既然這種技術可以操作遠程電腦的數據,他當然是網路通信技術。 2、.NET Remoting使用的技 ...
  • 先看看列印入庫單的效果圖,看如下: 客戶要求合計一行,要求大寫中文數字。XtraReport報表是如何做出以上圖的效果呢?因為是要把數字轉成大寫中文數字,得先準備數字轉大寫中文數字的函數。因網上有很多方法,我這裡就不上傳代碼了。這裡只說一下XtraReport報表創建以上收貨單報表大寫數字操作。新建 ...
  • .NET Core CSharp 中級篇 2 1 本節內容為裝箱與拆箱 簡介 裝箱和拆箱是一個相對抽象的概念。你可以想象一下一堆滿載貨物的大卡車,他是由許多工人將貨物集中堆放裝入的,對於我們而言在沒有打開貨箱的時候,我們可以知道這是一輛運貨的卡車,裡面有著許多貨物,但是具體貨物是什麼,我們只有打開後 ...
  • 這幾天本人接了個檔案管理查詢系統的小項目,踩過的坑。 其實功能都挺簡單的,大致要求客戶有很多pdf文檔,為了方便管理,所有要開發一個相當於文件管理系統,本人正好有現成的文件管理系統,修改下就可以。其中客戶要求pdf需要放到其他的盤符,不能和應用程式在一起,這個解決起來非常方便。系統上線了後,因為客戶 ...
  • 這些區域性通常分為三個集合:固定區域性、非特定區域性和特定區域性。 固定區域性不區分區域性。可以使用空字元串 ("") 按名稱或者按區域性標識符 0x007F 來指定固定區域性。它與英語語言關聯,但不與任何國家/地區關聯。它幾乎可用在要求區域性的“全局化”命名空間中的所有方法中。 非特定區域性是與某 ...
  • demo地址: "ABP.WindowsService" 該文章是系列文章 "基於.NetCore和ABP框架如何讓Windows服務執行Quartz定時作業" 的其中一篇。 參考:https://aspnetboilerplate.com/Pages/Documents/Logging ABP框架 ...
  • 前言:何謂版本控制系統吶?有兩種說法:一種叫法為SCM,==source code management (源代碼管理系統)另一種說法為VCS,==version control system (版本控制系統),既然兩種叫法都可以的話,姑且把她叫成版本控制系統吧,從名稱不難看出此系統一是用來解決代碼 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...