C#中大List的記憶體分配

来源:http://www.cnblogs.com/ldyblogs/archive/2017/11/06/list.html
-Advertisement-
Play Games

之前在開發中只用到List的時候幾乎就是拿過來就用,從來沒有考慮過List的記憶體分配問題,試想一個有10萬元素的List的在構造和添加元素時記憶體是如何變化的呢?在MSDN上關於List的Capacity屬性是這麼解釋的,也就是說,當我們添加的元素數量小於等於Capacity的值時,List是不會重新 ...


 

之前在開發中只用到List的時候幾乎就是拿過來就用,從來沒有考慮過List的記憶體分配問題,試想一個有10萬元素的List的在構造和添加元素時記憶體是如何變化的呢?在MSDN上關於List的Capacity屬性是這麼解釋的,也就是說,當我們添加的元素數量小於等於Capacity的值時,List是不會重新調整內部數據結構,也就是不會重新申請或者分配記憶體,而當我們添加的元素數量大於Capacity 的值時,List就會不斷的調整內部數據結構或者重新申請分配記憶體,這樣的話對效率肯定會有一定的影響的。

 

當我們使用List<T> list = new List<T>();實例化一個List對象是,.Net Framework只是在記憶體中申請了一塊記憶體在存放list對象本身,系統此時並不知道list會有多少item元素。當我們向list添加第一個item時,list會申請能存儲4個Item元素的存儲空間,此時Capacity是4,但是當我們添加到第五個item時,此時的Capacity就會變成8,也就是當list發現元素的總數大於Capacity數量時,會主動申請並重新分配記憶體,當我們添加到第九個item時,Capacity不是12而是16,也就是說list每次申請的記憶體數量都是之前item元素數量兩倍。然後將當前所有的item元素系但添加的元素複製到新的記憶體。

 

大家可以看到,如果list需要添加的元素特別多時,list會不斷地申請心記憶體,複製已有元素和新加元素到新記憶體,這個過程會產生資源的浪費及性能問題。

 

如果當設置的Capacity值遠大於list的實際元素數量時,應使用TrimExcess()方法釋放點未使用的記憶體。

class Program
    {
        static void Main(string[] args)
        {
            List<Part> parts = new List<Part>();

            Console.WriteLine("\nCapacity: {0}", parts.Capacity);

            parts.Add(new Part() { PartName = "crank arm", PartId = 1234 });
            parts.Add(new Part() { PartName = "chain ring", PartId = 1334 });
            parts.Add(new Part() { PartName = "seat", PartId = 1434 });
            parts.Add(new Part() { PartName = "cassette", PartId = 1534 });
            parts.Add(new Part() { PartName = "shift lever", PartId = 1634 });

            Console.WriteLine();

            foreach (Part aPart in parts)
            {
                Console.WriteLine(aPart);
            }

            Console.WriteLine("\nCapacity: {0}", parts.Capacity);
            Console.WriteLine("Count: {0}", parts.Count);

            parts.TrimExcess();
            Console.WriteLine("\nTrimExcess()");
            Console.WriteLine("Capacity: {0}", parts.Capacity);
            Console.WriteLine("Count: {0}", parts.Count);

            parts.Clear();
            Console.WriteLine("\nClear()");
            Console.WriteLine("Capacity: {0}", parts.Capacity);
            Console.WriteLine("Count: {0}", parts.Count);


            Console.Read();
        }
    }

    public class Part
    {
        public string PartName { get; set; }
        public int PartId { get; set; }
        public override string ToString()
        {
            return "ID: " + PartId + "   Name: " + PartName;
        }
    }

知道了list的Capacity及TrimExcess()方法的用處,保證有限的記憶體空間能夠得到合理的運行,歸納起來主要有以下幾點:

1.當我們實例化一個List對象時,如果知道最大的Item元素時,應該在實例化List<T>時制定Capacity的數量,直接使用List的構造方法public List(int capacity);就可以。

2.當由於不斷的從list中remove掉大量元素時,此時list記憶體仍占用一部分不需要使用的空間,造成記憶體的浪費,此時可以調用TrimExcess方法來釋放多餘的記憶體。

以上是我對list的記憶體分配一點淺顯的理解,還請大家多多指教,歡迎拍磚。

以上動圖由“圖鬥羅”提供


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

-Advertisement-
Play Games
更多相關文章
  • Linux/Unix 命令格式: 命令名 [選項] [參數] 註:[]中的內容代表內容可以省略 例:$ ls $ ls -l #-l 是選項 開始符號: 文件名 或 文件夾名 .當前文件夾 ..上一級文件夾 ~用戶主目錄(家目錄) 查看類: pwd命令: 使用: 用於顯示當前操作的位置的路徑(當前工 ...
  • 新的剛來到,舊的就忘掉。學習 AspNet Core 2.0,沒有好的例子,是很痛苦的。《Pro ASP.NET Core MVC 2》中的 SportsStore 值得一看,不妨下載研究一下: 準備 1. 使用 Ubuntu 系統 2. 安裝 NetCore2.0 3. 安裝 VSCode 4. ...
  • 最近開發一個新項目,使用了asp.net core 2.0,採用webapi開發後臺,postgresql為資料庫。最先來的問題就是上傳文件的問題。 POST文件的一些坑 使用預設模板創建webapi的controller後,post請求,預設有 請求使用了 標記,用來指示用請求體里獲得數據。 對於 ...
  • 本次是結合近乎免費源碼版產品代碼進行的介紹,關於近乎產品下載可以訪問:www.jinhusns.com 下載免費源碼版本瞭解。 ...
  • 一、Model層 二、控制器層 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.Mvc; 6 using Mvc_Demo. ...
  • 首先,寫這篇文章的原因是因為最近某一個項目中的介面被人為調用了,導致了資料庫數據被串改。雖然是內部人無意點的,但還是引起了我的擔憂,所有整理了下關於Webapi的相關簽名機制。 一、我們在開發介面時,有時候嫌麻煩就懶進行相關的驗證或只進行一些簡單的驗證,這樣客戶端就可以直接調用:如 調用Webapi ...
  • --DateTime 數字型 System.DateTime currentTime=new System.DateTime(); 取當前年月日時分秒 currentTime=System.DateTime.Now; 取當前年 int 年=currentTime.Year; 取當前月 int 月=c ...
  • 在web.config 配置文件增加以下節點配置信息: <!--支持跨域--> <system.webServer> <httpProtocol> <customHeaders> <!-- 指定請求的方式 --> <add name="Access-Control-Allow-Methods" va ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...