<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      簡單講講.NET GC垃圾回收的“分代處理,標記、清除、壓縮”

      GC垃圾回收

      GC垃圾回收是.NET(CLR)運行時的核心組件,其控制堆中的內存分配與回收,減輕開發者手動管理內存的負擔。避免內存泄露和懸空指針(對象內存被釋放后仍被訪問)等問題。

      其核心基于分代收集和標記-清除-壓縮算法。

      如果基本知識已經看過,但壓縮機制還未弄清除。可直接跳轉到下方壓縮標題,也許會給你些新的思路。

      GC觸發機制

      當第0代內存分配容量超出閾值,則會觸發垃圾回收。閾值動態調整,通常為幾mb。

      GC可以手動觸發,調用GC.Collect();靜態函數。(通常在調試或場景切換時使用)

      混合觸發,調用GC.AddMemoryPressure();

      混合觸發會提示GC當前非托管內存壓力增大,但是否觸發回收由GC策略決定(基于托管堆占用率、碎片率等綜合判斷)

      使用混合觸發時如果托管堆內存充足,GC可能延遲回收。

      分代收集

      GC會根據分代收集將堆中的對象分為3代,Gen 0、Gen 1、Gen2。還有一個獨立存放大占用對象的大對象堆LOH。

      在對象剛開始創建時會將其放入第0代內存,當0代內存存儲數據容量超出閾值(動態調整,通常256kb-4mb)時,會觸發GC。

      GC會把0代內存中仍被引用的對象標記為存活,未被引用的對象標記為垃圾。GC將垃圾對象清除釋放空間。

      然后將0代中所有(非固定對象)標記為存活的對象復制到下一代內存中(如果是0代就復制到1代中,如果是1代就復制到2代)

      復制完對象到下一代內存中后,其原本所在的內存空間會被回收。

      這里要注意,如果對象占用空間大與等于85kb(.NET8中LOH閾值提升至100kb),那么該對象會直接存入大對象堆LOH中。

      堆段 GC調用
      Gen 0 新建對象占用小于等于85kb(.NET8中LOH閾值提升至100kb)的對象存入該內存。 Gen 0存儲數據容量超出閾值時GC調用。
      Gen 1 GC調用時0中被引用的對象會被復制到該內存。 在0代垃圾回收后,會判斷Gen 1中的對象和Gen 0中的對象占用容量之和是否大于了Gen 1的動態閾值,如果超過了那么Gen 1就會調用GC,其調用GC時Gen 0也會被GC連帶檢查。
      Gen 2 GC調用檢查Gen 1內存時會將Gen 1中被引用的對象復制到該內存 Gen 2調用GC時所有內存0、1、2、LOH都會被GC檢查處理。
      LOH 新鍵對象占用大于85kb(.NET8中LOH閾值提升至100kb),直接放入LOH中。 自身不會觸發GC,只在Gen 2觸發GC時,才會被連帶處理(無論LOH空間是否已滿)。就算手動調用GC也不會回收LOH。

      每代內存都會在內存中劃分自己的地址范圍,其中0代與1代的地址劃分是嚴格連續的。

      如果0代占0x0000-0x1000,1代就一定占0x1001-0x2000。

      2代與LOH是獨立堆段,其地址劃分與0/1內存無連續性。

      壓縮

      為什么會有壓縮?首先我們需要講講內存碎片。
      我們在將對象存入2代或LOH內存時都是邏輯連續的(包含內存間隙),我們可以將各個對象看成是一個個在鍵盤中挨著的鍵帽。
      在未清理時,每個鍵帽都是挨著的,但是在調用GC后,發現有些鍵帽壞了,那么GC會將那些鍵帽清除。
      而這時我們再來看鍵帽,已經不再是密集一個個排列的了,他們中間空出了壞鍵帽的位置。這些空出的位置就是內存碎片。
      在這時我們新加入了一個鍵帽,如果內存碎片中有一個的容量足以放入新鍵帽那該內存碎片就有可能被再次填上。
      但是如果該對象的占用比空出位置小呢?那么就會產生一個更小的內存碎片。這個碎片有可能很難再放入新加入的鍵帽(對象)了,那么這個碎片就很可能完全被浪費。
      就算這時還有能存放一些一般容量大小的碎片,但這種碎片一多,多到到處都是,到處都是鍵帽隔著碎片,已經沒有空余的大空間存放像是回車刪除Shift這樣比正常鍵帽要大的鍵帽了,
      但這時可存儲容量卻顯示仍然夠用,這時候來了一個回車,回車進來一看,雖然可存放空間仍有富裕,但是那只是內存碎片的總容量,而現在沒有一個碎片能放下回車。這時就出問題了,所以我們引用了壓縮算法。

      壓縮就是在內存碎片過多時,將各個對象移動,讓他們再次變成一個連續的結構。這樣原本存在的一個個小空位就消失了。

      Gen 0內存和Gen 1內存中的對象是不進行壓縮的。其直接復制對象到新地址。所以不會有內存碎片

      Gen 2中的對象可能會壓縮,其會根據Gen 2中的碎片率來決定是否壓縮。

      LOH從.NET4.5.1版本開始可以通過顯示設置強制壓縮

      //設置LOH壓縮模式,LOH壓縮會在下次Gen 2觸發GC時進行壓縮。
      //LOH壓縮執行完,標識符會自動重置。如果想要LOH再次壓縮須重新設置
      GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
      

      壓縮會更新其所在堆段中的所有對象地址,而要實現更新則需要使用Stop-The-World將所有用戶線程暫停。

      也就是在壓縮時,應用程序會整個暫停。在用戶的視角下不如說更像是卡頓。

      POH固定對象堆.NET 5+新特性

      //創建固定對象,不會被GC移動
      var pinnedObj = GC.AllocateArray<byte>(size: 1024, pinned: true);
      

      以這種方式創建的對象,不會被GC移動。就算是位于0代內存或1代內存也不會被GC在釋放內存遷移對象到下一層時移動。

      比如固定對象創建在了0代內存中,這時觸發垃圾回收。其他非固定且被引用的對象會被遷移到1代內存中,而固定對象會固定在0代內存不會被遷移。

      但我們也可以明顯看出這種形式對象的弊端,它會阻礙壓縮操作,可能加劇內存碎片。需謹慎使用。且固定對象使用完須及時釋放。

      posted @ 2025-08-13 21:04  yangtao2333  閱讀(48)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产永久免费高清在线观看| 精品无码国产污污污免费| 欧美日韩在线视频| 精品熟女日韩中文十区| 乱人伦中文视频在线| 中文字幕乱码熟妇五十中出 | 国产亚洲一区二区三区av| 无码熟妇人妻AV在线影片最多| 少妇人妻偷人精品免费| 丝袜美腿亚洲综合第一区| 国产成人a∨激情视频厨房| 亚洲嫩模一区二区三区| 色吊丝av熟女中文字幕| 浏阳市| 巨熟乳波霸若妻在线播放| 人妻放荡乱h文| 乱码中文字幕| 国产精品福利自产拍久久| 国精品无码一区二区三区左线| 亚洲欧洲久久激情久av| 国产小受被做到哭咬床单GV| 国产成人午夜福利在线播放| 亚洲熟女乱综合一区二区| 亚洲精品一区二区动漫| 免费的很黄很污的视频| 蜜臀久久99精品久久久久久| 伊人成伊人成综合网222| 亚洲日本欧洲二区精品| 色国产视频| 国产av普通话对白国语| 亚洲色一色噜一噜噜噜| 韩国美女福利视频一区二区| 日本一区二区三区在线播放| 99久久国产福利自产拍| 国产999久久高清免费观看| 亚洲精品一区二区三区中文字幕| 自拍偷区亚洲综合第二区| 久久综合久中文字幕青草| 久久亚洲精品无码播放| 久久久精品94久久精品| 亚洲中文字幕在线精品一区|