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

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

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

      CLR探索系列:GC Heap架構及其實現(垃圾回收系列)

      CLR探索系列的研究DotNet下的垃圾回收器這幾個博文里,就先說說GC Heap結構吧,至于垃圾回收的詳析算法實現,以后再寫了。

      在一個托管進程被創建以后,在托管進程的內存空間里面,包含了System DomainShared DomainDefault Domain,以及一系列的Heap,有ProcessHeapJIT Code HeapGC Heap以及LOH

      DotNetCLR的實現中,GC heapLOHLarge Object Heap)是包含在一個類里面實現的。這就造成了在內存中,一個GC Heap后面緊跟著的就是LOH Heap。在實現的時候,一個gc_heap類里面包含了一個GC的結構類,以及一個LOH

      一個GC Heap的結構大致如下:

      gcheap.jpg



             上面是一個GC Heap的大致結構。從上面到下面是從低地址到高地址。有的時候,需要找一個需要的存在了很久的Object的時候,并不是往高地址去尋找,也有可能存在于低地址區域,這個和每個Generation的大小的動態改變有關。

             說到這里,就會提到一個非常有趣的概念,“策略”。這個是GC開發小組的開發人員在研究呢很久性能和用戶的操作以及內存管理之間的平衡只會整出來的一個比較有趣的概念。在垃圾回收的過程中加入了“策略”。譬如一個Generation 0代占有256KB的內存大小,如果在實際的程序的運行過程中發現新對象的創建特別頻繁,那么GC EE就會自動增加這個Generation 0的大小。

             在說明一個GC Heap的結構的時候,先用windbg+sos來看看一個用戶態運行的程序的GC Heap里面都有些啥:

             0:003> !eeheap

      =======================================

      Number of GC Heaps: 1

      generation 0 starts at 0x00ca1018

      generation 1 starts at 0x00ca100c

      generation 2 starts at 0x00ca1000

      ephemeral segment allocation context: none

       segment    begin allocated     size

      00161e00 790d5588  790f4b38 0x0001f5b0(128432)

      00ca0000 00ca1000  00ca3ff4 0x00002ff4(12276)

      Large object heap starts at 0x01ca1000

       segment    begin allocated     size

      01ca0000 01ca1000  01ca3250 0x00002250(8784)

      Total Size   0x247f4(149492)

      ------------------------------

      GC Heap Size   0x247f4(149492)

      =======================================

      可以看到,在上面顯示的GC Heap的結構中,一個GC Heap里面有兩個Heap Segment,緊接著Heap Segment的,是LOH

       

      在上面的一個GC Heap中,分成三個Generation,最年輕的ObjectG 0中。這些Generation是保存在一個一個的Heap Segment里面的。一個Heap Segment可以包含兩個Generation或者三個,或者更多。而一個Generation可以跨越多個Heap Segment

       

      一個GC Heap主要有一個或者是多個Heap Segment組成。然后在GC Heap的最后還有一個保留區域,用來保存一些比較特別的Object

      譬如有一種類型的Object叫做pinned Object。當某個Object存在于Generation 0的內存區域中的時候,如果有其它的外部指針指向了它,再進行一次局部的垃圾回收的時候,這個Object就是不能被移走的,這樣的對象就叫做pinned Object。但是,為了保證垃圾回收器的效率和性能,最年輕的Generation在每次垃圾回收的時候就會被refresh一次,清空所有的對象。先前存在的對象要么被移動到更老的Generation中去,而象這種pinned Object,就會被移動到GC Heap保留的內存區域里面去。

       

      一個Heap Segment中可以包含一個或者多個Generation,這個是可以動態擴展的。

       

      緊接著GC Heap的內存區域,就是Large Object Heap。在默認情況下,超過85000byte的對象就被保存到這里。

      因為在LOH里面的對象清理一次對系統資源的消耗比較大,在存儲大對象的時候,就會首先根據一個ObjectMetaTable,掃描一遍來判斷這個對象有沒有對別的對象的引用。如果有的話,這一類對象就會存儲在一起,而沒有對其它對象引用的對象就會存在其余的另外一個區域。

      這樣做的好處,主要體現在性能的優化上面。在進行垃圾清理的時候,確定一個Object是否是live ObjectLOH的這種布局方式可以減少很多不必要的對一個對象的掃描工作。

       

      接下來,看看這些結構都是如何實現的,首先看看基本類gc_heap里面都有些什么:

       

      //class definition of the internal class

      class gc_heap

      {

      //GC Heap

         friend class GCHeap;

         friend class CFinalize;

         friend void ProfScanRootsHelper(Object*&, ScanContext*, DWORD);

         friend void GCProfileWalkHeap();

       

      public:

      //創建一個Heap Segment

          heap_segment* make_heap_segment (BYTE* new_pages, size_t size);

      //創建一個大對象堆,包含引用的對象

          l_heap* make_large_heap (BYTE* new_pages, size_t size, BOOL managed);

       

          gc_heap* make_gc_heap();

          void destroy_gc_heap(gc_heap* heap);

       

          static

          HRESULT initialize_gc  (size_t vm_block_size,

                                  size_t segment_size,

                                  size_t heap_size);

          static

          void shutdown_gc();

       

             //allocate object in heap segments.這個分配動作并不分配大對象,只是分配在GC Heap上面的對象,而不是LOH上面的。LOH上面的對象分配是下面的allocate_large_object方法。

          static

          CObjectHeader* allocate (size_t jsize,

                                   alloc_context* acontext );

       

          CObjectHeader* try_fast_alloc (size_t jsize);

       

       

             //allocate large object method,區別上面的allocate方法。

          static

          CObjectHeader* allocate_large_object (size_t size, BOOL pointerp, alloc_context* acontext);

             //部分收集,對第幾代進行垃圾收集。

          static

          int garbage_collect (int n);

             //update brick table and card table

          static

          int grow_brick_card_tables (BYTE* start, BYTE* end);

       

      protected:

             //獲取一個Heap segment

          static

          heap_segment* get_segment ();

             //得到lHeap,屬于保存large objects with pointers

          static

          l_heap* get_heap();

       

          static

          BOOL allocate_more_space (alloc_context* acontext, size_t jsize);

       

          void reset_allocation_pointers (generation* gen, BYTE* start);

          void delete_heap_segment (heap_segment* seg);

          void delete_large_heap (l_heap* hp);

          void adjust_ephemeral_limits ();

       

          void make_generation (generation& gen, heap_segment* seg,

                                BYTE* start, BYTE* pointer);

          int heap_grow_hook (BYTE* mem, size_t memsize, ptrdiff_t delta);

          int heap_pregrow_hook (size_t memsize);

       

             //card table的操作。

          size_t card_of ( BYTE* object);

          BYTE* brick_address (size_t brick);

          size_t brick_of (BYTE* add);

          BYTE* card_address (size_t card);

          size_t card_to_brick (size_t card);

          void clear_card (size_t card);

          void set_card (size_t card);

          BOOL  card_set_p (size_t card);

          int grow_heap_segment (heap_segment* seg, size_t size);

          void copy_brick_card_range (BYTE* la, BYTE* old_card_table,

                                      short* old_brick_table,

                                      heap_segment* seg,

                                      BYTE* start, BYTE* end, BOOL heap_expand);

          void copy_brick_card_table_l_heap ();

          void copy_brick_card_table(BOOL heap_expand);

          void clear_brick_table (BYTE* from, BYTE* end);

          void set_brick (size_t index, ptrdiff_t val);

       

             //根據是否是調試模式來確定是否進行引用的驗證。

          static

          gc_heap* heap_of (BYTE* object, BOOL verify_p =

      #ifdef _DEBUG

                            TRUE

      #else

                            FALSE

      #endif //_DEBUG

      ){return (gc_heap*)0;}

       

             //下面的這些方法是在進行垃圾回收整理移動和復制對象的時候適用的。包括一系列的針對object還有card table以及進程的makecopyfixverify等動作。

          BYTE* mark_object(BYTE* o );

          BYTE* mark_object_class (BYTE* o );

          void copy_object_simple_const (BYTE** o );

          void get_copied_object (BYTE** o );

          void scavenge_object_simple (BYTE* o );

             //pinned object被移動到保留的Heap segment區域里面去。

          void scavenge_pinned_object (BYTE* o );

          void mark_object_internal (BYTE* o );

          BYTE* next_end (heap_segment* seg, BYTE* f);

          void fix_card_table ();

          void verify_card_table ();

          void mark_through_object (BYTE* oo );

          BOOL process_mark_overflow (int condemned_gen_number);

          void mark_phase (int condemned_gen_number, BOOL mark_only_p);

             //把一個object整成pinned object

          void pin_object (BYTE* o, BYTE* low, BYTE* high);

             //update brick table

          size_t update_brick_table (BYTE* tree, size_t current_brick,

                                     BYTE* x, BYTE* plug_end);

       

             //cardbricktable的操作

          void clear_cards (size_t start_card, size_t end_card);

          void clear_card_for_addresses (BYTE* start_address, BYTE* end_address);

          void copy_cards (size_t dst_card, size_t src_card,

                           size_t end_card, BOOL nextp);

          void copy_cards_for_addresses (BYTE* dest, BYTE* src, size_t len);

          BOOL ephemeral_pointer_p (BYTE* o);

          void fix_brick_to_highest (BYTE* o, BYTE* next_o);

          void copy_through_cards_helper (BYTE** poo, unsigned int& ngen, card_fn fn);

          void copy_through_cards_for_segments (card_fn fn);

       

       

       

          /* ------------------- per heap members --------------------------*/

      public:

          BYTE* card_table;

          short* brick_table;

          BYTE* lowest_address;

          BYTE* highest_address;

       

      protected:

          heap_segment* ephemeral_heap_segment;

             //定義一個GC可以有幾個Generation

          int         condemned_generation_num;

          BYTE*       scavenge_list;

          BYTE*       last_scavenge;

          BOOL        pinning;

          BYTE*       gc_low; // lowest address being condemned

          BYTE*       gc_high; //highest address being condemned

          size_t        segment_size; //size of each heap segment

          size_t      lheap_size;  //size of each lheap

          BYTE*  min_overflow_address;

          BYTE*  max_overflow_address;

       

          GCSpinLock more_space_lock; //lock while allocating more space

          GCSpinLock gc_lock; //lock while allocating more space

       

          dynamic_data dynamic_data_table [NUMBERGENERATIONS+1];

       

          //Large object support

          l_heap* lheap;

          BYTE* lheap_card_table;

          gmallocHeap* gheap;

          large_object_block* large_p_objects;

          large_object_block** last_large_p_object;

       

          large_object_block* large_np_objects;

             //定義多大的對象就會保存到LOH中去。這個默認定義的大小是85000

          size_t large_objects_size;

          size_t large_blocks_size;

       

          BOOL gen0_bricks_cleared;

       

       

          CFinalize* finalize_queue;

       

          /* ----------------------- global members ----------------------- */

      public:

             //定義最大支持幾代的垃圾回收

          static

          int g_max_generation;

             //定義一個保留的內存區域

          static

          size_t reserved_memory;

          static

          size_t reserved_memory_limit;

       

      }; // class gc_heap

       

      在上面的gc _heap類中,將對傳統意義上面的GC Heap的管理和對LOH的管理,整合到了一起。這兩部分對于垃圾回收是關系密切不可分離的兩個部分,雖然LOH并不會有類似于帶的概念,也不進行compaction的操作,但是個人更加愿意把LOH歸類于垃圾回收的一個子系統。

       

      上面說到,LOHGC Heap一個很大的不同,就是LOH并不進行Heap的壓縮工作Heap的壓縮是說,譬如在Generation 1中,經常進行Object的分配和finalize,就會造成這個區域的很多碎片,這個對于整個Heap的效率內存空間都有比較大的負面影響。關于對HeapCompaction壓縮,這是一個非常有趣好玩的事情,當然不是一兩句能夠說清楚的,這篇文章的重點在于說說GC Heap的結構,這個有趣的解決方法就在以后的博文里面探討把。

      這里只說說LOHHeap為什么沒有Compaction。因為在一個LOH中移動一個大對象是非常消耗系統資源的。LOH在實現的時候,是采用了開源的malloc-style heap的實現。這個實現中并沒有涉及到Heap的壓縮。基于性能的考慮,MS采用了一種折中的解決方案。給這個LOH中劃分出了兩種不同類型的Heap,也就是上面提到的,一種存放不包含pointerHeap,另外一種是包含pointerHeap。對對象的這種判斷,是基于其Metatable的。



      接下來,看看Heap Segment的實現:

      class heap_segment

      {

      public:

             //指向已經分配了的內存的末端

          BYTE*           allocated;

          BYTE*           committed;

             //指向一個segment的保留區域

          BYTE*           reserved;

          BYTE*           used;

          BYTE*           mem;

             //對所有的Heap segment都是鏈在一起成一條鏈的。

          heap_segment*   next;

          BYTE*           plan_allocated;

          BYTE*           padx;

       

          BYTE*           pad0;

      #if ((SIZEOF_OBJHEADER+ALIGNFIXUP) % 8) != 0

          BYTE            pad1[8 - ((SIZEOF_OBJHEADER+ALIGNFIXUP) % 8)];   // Must pad to quad word

      #endif

          plug            mPlug;

      };

       

      然后看看一個Heap segment里面的Generation是如何實現的:

      class generation

      {

      public:

             //分配上下文

          alloc_context   allocation_context;

             //這個generation存在的Heap segment

          heap_segment*   allocation_segment;

          BYTE*           free_list;

          heap_segment*   start_segment;

          BYTE*           allocation_start;

          BYTE*           plan_allocation_start;

          BYTE*           last_gap;

             //一個Generation里面剩余的空閑未分配空間

          size_t          free_list_space;

             //generation里面的已經分配的空間的大小

          size_t          allocation_size;

      };

       

      還有一個問題提一下,就是在最上面的gc_heap的實現的時候,一個GC Heap里面的Heap Segment可以方便的添加和擴展,而且,在邏輯結構上面,同一個Generation的東西,可以分布在一個或者多個Heap segment里面。同時,gc_heap類的設計,也保證了可以方便的擴展一個GC Heap里面的Generation的個數。

       

      對一個GC Heap的架構設計及其實現,就寫到這里吧,雖然有許多細節問題沒有寫出來,敲的太多了,但是主要的問題也算講清楚了吧 ^_^

      下面的文章中,就探索下垃圾回收的算法和回收實現機制,以及在垃圾回收里面的比較棘手的問題的挺有趣的解決方案吧。

      posted on 2008-02-20 10:51  lbq1221119  閱讀(5500)  評論(17)    收藏  舉報

      導航

      主站蜘蛛池模板: 亚洲乱码av中文一区二区| 国产国拍亚洲精品永久软件| 女人被狂躁c到高潮| 国产精品区一二三四久久| 色一乱一伦一图一区二区精品| 平乡县| 高清偷拍一区二区三区| 东京一本一道一二三区| 免费无遮挡无码永久在线观看视频| 成人午夜大片免费看爽爽爽| 欧美伦费免费全部午夜最新| 日本熟妇XXXX潮喷视频| 亚洲av激情久久精品人| 国产在线拍揄自揄拍无码视频| 色九九视频| 色午夜久久男人操女人| 精品无码人妻一区二区三区| 欧洲精品色在线观看| 久久亚洲精品情侣| 亚洲 中文 欧美 日韩 在线| 在线无码免费看黄网站| 亚洲一区二区三区水蜜桃 | 国产精品国三级国产专区| 免费看女人与善牲交| 国产精品自拍中文字幕| 深夜av免费在线观看| √天堂资源地址在线官网| 99在线小视频| 亚洲av永久无码天堂影院| 成人精品老熟妇一区二区| 亚洲精品国产一二三区| 国产对白老熟女正在播放| 国产成人精品亚洲精品日日| 亚洲国产精品综合久久20| 99在线视频免费观看| 久久精品国产精品第一区| 欧美牲交a欧美在线| 亚洲最大av一区二区| 亚洲有无码中文网| 久久亚洲国产品一区二区| 国产精品亚洲А∨怡红院|