小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

垃圾回收GC:.Net自動(dòng)內(nèi)存管理 上(一)內(nèi)存分配

 kiki的號(hào) 2017-06-20

垃圾回收GC:.Net自動(dòng)內(nèi)存管理 上(一)內(nèi)存分配

前言


.Net下的GC完全解決了開(kāi)發(fā)者跟蹤內(nèi)存使用以及控制釋放內(nèi)存的窘態(tài)。然而,你或許想要理解GC是怎么工作的。此系列文章中將會(huì)解釋內(nèi)存資源是怎么被合理分配及管理的,并包含非常詳細(xì)的內(nèi)在算法描述。同時(shí),還將討論GC的內(nèi)存清理流程及什么時(shí)清理,怎么樣強(qiáng)制清理。


引子


為你的應(yīng)用程序?qū)崿F(xiàn)合理的資源管理是一件困難的,乏味的工作。這可能會(huì)把你的注意力從你當(dāng)前正在解決的實(shí)際問(wèn)題中轉(zhuǎn)移到它身上。那么,如果有一個(gè)現(xiàn)有的機(jī)制為開(kāi)發(fā)者管理令人厭惡的內(nèi)存管理,會(huì)不會(huì)是件快意人心的事?答案是YES!在.Net中, 有一種垃圾回收機(jī)制叫GC。


每一個(gè)程序都需要使用一些計(jì)算機(jī)資源,如內(nèi)存,顯卡,網(wǎng)絡(luò),數(shù)據(jù)庫(kù)等等。實(shí)際上,在一個(gè)面向?qū)ο蟮沫h(huán)境里,每一個(gè)類型都代表著程序需要使用的資源。如果要用到這些資源,則需要分配內(nèi)存呈現(xiàn)這個(gè)類型。下面是訪問(wèn)這些資源的步驟:

  1. 分配內(nèi)存給類型資源。
  2. 初始化內(nèi)存和類型資源并使資源可用。
  3. 利用這些資源來(lái)訪問(wèn)類型實(shí)例成員信息(按需重復(fù))。
  4. 銷毀并清理資源
  5. 釋放內(nèi)存

這看起來(lái)很簡(jiǎn)單,但卻是程序錯(cuò)誤的根本來(lái)源。有多少次程序員忘記釋放閑置內(nèi)存?有多少次程序員試圖訪問(wèn)已經(jīng)釋放的內(nèi)存?

      

這兩種BUG是最糟糕的情況,因?yàn)樗鼈儗?dǎo)制的異常結(jié)果和發(fā)生時(shí)間是不可預(yù)測(cè)的。對(duì)于其它的BUG,當(dāng)你看到程序運(yùn)行錯(cuò)誤時(shí),直接修復(fù)就行了。這兩種BUG最容易造成程序資源泄漏(浪費(fèi)內(nèi)存)和程序?qū)ο蟊罎?不穩(wěn)定),而且還會(huì)促使應(yīng)用程序在不可預(yù)知的時(shí)間產(chǎn)生不可預(yù)知的行為。當(dāng)然了,有許多工具可用于跟蹤監(jiān)測(cè)這種BUG。

     

當(dāng)我們測(cè)試GC時(shí),你應(yīng)該知道它徹底解決了開(kāi)發(fā)者跟蹤內(nèi)存使用及確定何時(shí)釋放內(nèi)存的問(wèn)題。然而,垃圾回收GC并不了解任何關(guān)于類型在內(nèi)存中代表的資源。這意味著,GC不知道也不會(huì)去執(zhí)行第四步:銷毀并清理資源。在.net framework中,程序員在方法Close,Dispose,F(xiàn)inalize中編寫(xiě)有關(guān)銷毀清理資源的代碼,后續(xù)文章中會(huì)介紹。不過(guò),GC能夠決定什么時(shí)去自動(dòng)調(diào)用這些方法。

    

有一些類型資源不需要清理。如,Rectangle類型可以通過(guò)銷毀它在內(nèi)存中的left,right,width和height從而被徹底清理。另一方面,一個(gè)文件類型資源或網(wǎng)絡(luò)連接類型資源則需要非常明確的清理代碼來(lái)銷毀。我將解釋怎么適當(dāng)?shù)赝瓿蛇@些任務(wù)。現(xiàn)在,讓我們了解一下內(nèi)存是怎么分配的以及資源是怎么初始化的。


內(nèi)存分配



.NET CLR將所有資源分配到托管堆上,這有點(diǎn)像C語(yǔ)言中的堆但是你不用去釋放資源因?yàn)殚e置資源在.NET中將被自動(dòng)釋放?,F(xiàn)在就有一個(gè)問(wèn)題了,托管堆是怎么知道一個(gè)對(duì)象什么時(shí)候?qū)⒉辉俦怀绦蚴褂茫课覍⒑?jiǎn)單介紹一下。
    
現(xiàn)今有很多的GC算法。每一個(gè)算法都針對(duì)某一特定環(huán)境進(jìn)行調(diào)優(yōu),進(jìn)而獲得最好的性能。這篇文章著重于.NET CLR使用的GC算法。讓我們從基本概念開(kāi)始。
      
當(dāng)一個(gè)線程初始化了,運(yùn)行時(shí)將預(yù)定一塊未使用的連續(xù)的地址空間。這塊地址空間就是托管堆深入淺出圖解C#堆與棧 C# Heap(ing) VS Stack(ing)。堆中同時(shí)維護(hù)著一個(gè)指針,我們叫它下一個(gè)對(duì)象指針。這個(gè)指針告訴我們下一個(gè)程序?qū)ο髮⒈环峙涞蕉阎械氖裁次恢?。在程序初期,這個(gè)指針被設(shè)置到最基本(可以理解為第一位置)的內(nèi)存地址。

程序使用new關(guān)鍵字創(chuàng)建一個(gè)新對(duì)象。這個(gè)操作首先需要確定預(yù)定的地址空間是否足夠存儲(chǔ)新對(duì)象(內(nèi)存空間是否足夠)。如果足夠,NextObjPtr(下一個(gè)對(duì)象指針)將指向堆中的此對(duì)象,對(duì)象構(gòu)造函數(shù)被調(diào)用,最后返回對(duì)象內(nèi)存地址。

托管堆(對(duì)堆與棧疑惑的朋友可以參考:深入淺出圖解C#堆與棧):

(NextObjPtr:下一個(gè)對(duì)象指針)


此時(shí),NextObjPtr將跳過(guò)此對(duì)象并指向下一個(gè)將要被存入的對(duì)象的內(nèi)存地址。如上圖,托管堆中有三個(gè)對(duì)象:A,B,C。下一個(gè)對(duì)象將會(huì)被放置到NextObjPtr指向的地址(即緊跟C之后)。

現(xiàn)在讓我們看看C語(yǔ)言的堆怎么分配內(nèi)存的。在c語(yǔ)言堆中,為一個(gè)對(duì)象分配內(nèi)存需要通過(guò)一個(gè)數(shù)據(jù)結(jié)構(gòu)鏈表。一旦發(fā)現(xiàn)一個(gè)較大的塊,則進(jìn)行分割塊,然后鏈表節(jié)點(diǎn)中的指針需要調(diào)整修改以保證所有數(shù)據(jù)原封不動(dòng)(C語(yǔ)言不熟,原文:In a C-runtime heap, allocating memory for an object requires walking though a linked list of data structures. Once a large enough block is found, that block has to be split, and pointers in the linked list nodes must be modified to keep everything intact. )。對(duì).NET中的托管堆來(lái)講,對(duì)象分配簡(jiǎn)單,只需要向指針添加一個(gè)值,相比而言這是非??斓摹J聦?shí)證明,在托管堆中分配一個(gè)對(duì)象幾乎像在線程棧里分配內(nèi)存一樣快!
   

到現(xiàn)在為止,聽(tīng)起來(lái)托管堆在速度上和實(shí)現(xiàn)簡(jiǎn)易性上要遠(yuǎn)遠(yuǎn)地優(yōu)秀于C語(yǔ)言的堆。但是,要使托管堆擁有這些優(yōu)點(diǎn)需要一個(gè)大前提:地址空間和存儲(chǔ)空間是無(wú)限大的。當(dāng)然,這有些不切實(shí)際,但托管堆必須使用一些機(jī)制原理來(lái)使這個(gè)所謂的假設(shè)成立。這個(gè)機(jī)制就是垃圾回收GC。讓我們看看它是怎么工作的。
      

當(dāng)一個(gè)程序使用new操作符創(chuàng)建一個(gè)新對(duì)象時(shí),可能沒(méi)有足夠的地址空間來(lái)放置它。為了檢測(cè)地址空間是否足夠,托管堆會(huì)償試把對(duì)象放到NextObjPtr位置,如果NextObjPtr移動(dòng)到超過(guò)地址空間邊界,那說(shuō)明堆已滿,GC則進(jìn)行垃圾回收。

   

實(shí)際上,GC會(huì)在第0代(后續(xù)文章會(huì)介紹GC中的代)被占滿時(shí)進(jìn)行垃圾回收。簡(jiǎn)單來(lái)說(shuō),GC中的代是GC實(shí)現(xiàn)的一種機(jī)制用來(lái)提高程序性能。原理上就是最新創(chuàng)建的對(duì)象屬于GC的年輕一代,應(yīng)用程序生命周期中較早創(chuàng)建的對(duì)象屬于較老一代。把對(duì)象分成不同的代可以讓GC知道要進(jìn)行垃圾回收的特定代,而不是回收整個(gè)托管堆。


總結(jié)

本篇文章是為了讓大家對(duì)垃圾回收GC和內(nèi)存分配有一個(gè)初步的認(rèn)識(shí),不得不說(shuō)了解內(nèi)存分配對(duì)于一個(gè)程序員是很重要的,如果你想寫(xiě)高性能代碼的話。雖然我們不必像使用C語(yǔ)言那樣手工分配內(nèi)存,但對(duì)內(nèi)存分配茫然無(wú)知的程序員多多少少會(huì)被鄙視一點(diǎn)點(diǎn)的(只是一點(diǎn)點(diǎn),好吧,沒(méi)有任何攻擊性,請(qǐng)不要誤解)。下一篇文章將繼續(xù)介紹垃圾回收GC的自動(dòng)內(nèi)存管理:內(nèi)存算法。


翻譯:http://msdn.microsoft.com/en-us/magazine/bb985010.aspx

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多