麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發(fā)設計 > 正文

IBM Java如何做到高性能GC的實現(xiàn)內幕

2019-11-18 13:13:46
字體:
來源:轉載
供稿:網(wǎng)友

  IBM JVM的GC分為三個步驟,Mark phase(標記),Sweep phase(清掃),Compaction phase(內存緊縮). 在了解這些過程之前,我們先看一下IBMjava中的對象的Layout和Heap lay out 一個Java對象在IBM vm中的結構如下
  1.size+flags
  2.mptr
  3.locknflags
  4.objectdata
  size+flags
    這是一個4byte的slot(32 平臺)。這個slot的主要功能就是描述對象的尺寸。由于IBMJava中的對象都是以8byte的倍數(shù)分配的,因此對象的尺寸其實就是真實尺寸/8存放在4byte的slot中。另外在這個slot的低三位是保留字段起到標記對象的作用。他們分別為 bit1:swapped bit,這個交換位被用于Compaction phase即內存緊縮階段使用。同時 這一位在標記堆棧溢出的時候(mark stack overflow)也被用于標記NotYetScanned狀態(tài). bit2:dosed bit.這個位用于標示這個對象是否被某個堆棧或者寄存器reference到了。
  
  假如這個標志被至位則這個對象就不能在當前的GC cycle中被刪除。而且假如某個reference指向的內存不是一個真實的reference比如是一個簡單的float 或者integer變量但是它的值恰巧就是Heap中某個Object的地址的時候,我們就不能修改這個refernece。這種對象的bit2也被置為1。bit3:pinned bit。標記一個對象是否是一個一個釘扣對象(PINNED object)。一個Pinned Object也不能被GC刪除,因為他們可能在Heap之外被reference到了。典型的一個例子就是Thread,還記得我上面說的僵死縣城么?它不能被刪除的道理就是這個。另外一種PinnedObject就是 JNI Object,即被本地代碼使用的對象。
  
  Mptr:
  在32平臺上也是4byte的slot。Mptr有兩個功能,
  1。假如mptr不是一個數(shù)組,則Mptr指向一個方法塊(method block),你可以通過這個method block來得到一個類塊(class block)。這個類塊,告訴你這個Object是屬于哪個class的實例。method block和class block由Class Loader分配,而不是heap在heap中進行分配
  2。假如mptr是一個數(shù)組(Array),mptr包含了這個對象中,數(shù)組的元素個數(shù)。 lockflags
  在32平臺上也是4byte的slot,但是這個slot只有低4位被用到。
  bit2:是array flag.假如這個位被置位,那么這個對象就是一個數(shù)組同時mptr字段就包含了數(shù)組的元素個數(shù)。
  bit4是hashed和moved bit.假如這個位被置位,那么他就告訴我們這個對象在被hashed以后被刪除了。
  Object Data:
  就是這個對象本身的數(shù)據(jù)
  
  Heap layout:
   heap top
   heap limit
   heap base
  
  heap base是heap的起始地址,heap top是heap的結束地址。heaplimit 是當前程序使用的那段heap可以進行擴展和收縮的極限。你可以用-Xmx參數(shù)在java運行的時候對heap top和heap base進行控制。
  Alloc bits 和 mark bits
    
   heap top allocmax markemax
   heap limit alloc size marksize
   heap base
  上面這個結構描述了heap和alloc bits 以及,markbits之間的關系。allocbits和markbits都是元素為1個bit的vector。他們與heap有同樣的長度,下面是兩個對象被分配以后在heap和兩個vector中的表現(xiàn)
  heaptop allocmax markmax
  
  heaplimit allocsize marksize
  
  object2top
  .
  .
  object2base object2allocbit object2markbit
  
  object1top
  .
  object1base object1allocbit
  
  如上面的結構,假如一個對象在heap被alloc出來,那么在allocbits中就標示出這個對象的起始地址所在的地址。allocbits中只標記起始地址。但是這個過程告訴我們這個對象在那里被創(chuàng)建,但是不告訴我們這個對象是否存活。當在mark phase中假如某一個對象比如object2仍然存活,那么就在markbits中對應的地址上標記一下The free list
  
  IBM jvm中的空閑塊用用一個free list鏈標示。如圖
  
  freechunck1 freechunck2 freechunckn
  size size size
  next------------->next--->.........next--->NULL
  freeStorage freeStorage freestorge
  有了這些基本概念我們來看看Mark phase的工作情況
  
  MarkPhase
  GC的Mark phase將標記所有還活著的對象。這個標記所有可達對象的過程稱為tracing。Jvm的活動狀態(tài)(active state)是由下面幾個部分組成的。1.每個線程的保存寄存器(saved registers)2.描述線程的堆棧3.Java類中的靜態(tài)元素3.以及局部和全局的JNI(Java Native Interface)引用。在Jvm中的方法調用都在C Stack上引發(fā)一個Frame。這個Frame包含了,對象實例,為局部變量的assignment結果或者傳入方法的參數(shù)。所有這些引用在Tracing過程中都被同等對待。實際上,我們可以把一個線程的堆棧看城一系列4-bytes slot的集合,然后對每一個堆棧都從頂向下對這些slot進行掃描。在掃描的過程中都必須校驗每個slot是否指向heap當中的一個真實的對象。因為在前面我就說過,很有可能這些slot值僅僅是一個int或float但是他們的值恰巧就等于heap中的一個對象地址。因此在掃描的時候必須相當?shù)谋J兀瑨呙璧臅r候必須保證所有的指針都是一個對象,而且這個對象沒有在GC中被刪除。只有符合下面條件的slot才是一個指向對象的指針。1.必須以8-byte的倍數(shù)分配的內存2.必須在heap的范圍之內(即大于heapbase小于heaptop)3.對應的allocbit必須置為1。滿足這些條件的對象引用我們稱為roots,并且把他們的dosed bit置為1表示不能被GC刪除。我想大家已經(jīng)知道C#中為何連Int和Float都是OBject的原因了吧。在C#中因為都是OBject因此,在tracing的過程中就減少了一次校驗。這個減少對性能起到很大的影響。 假如掃描完成,那么Tracing過程便能安全精確的執(zhí)行。也就是說我們可以在roots中通過reference找到他對應的objects,由于他們是真實的reference,那么我們就能夠在compactionphase中移動對應的對象并且修改這些reference。
  
  Trace過程使用了一個可以容納4k的slots的stack。所有的引用逐個push進入這個堆棧并且同時在markbits中進行標記。當push和mark的工作完成之后,我們開始pop出這些slot并且進行trace。
  
  常規(guī)的對象(非數(shù)組對象)將通過mptr去訪問classblock,classblock將會告訴我們從這個對象中找到的其他對象的reference在那里?當我們在classblock找到一個refernce以后,假如發(fā)現(xiàn)他沒有被mark,那么我們就在markallocbits中mark他然后把他再壓入堆棧。
  
  數(shù)組對象利用mptr去訪問每個數(shù)組元素,假如他們沒有mark則mark然后壓入堆棧。
  
  Trace過程一直持續(xù)進行,直到堆棧為空。
  
  MarkStack OverFlow
  
  由于markStack限制了尺寸,因此它可能會溢出。假如溢出發(fā)生,那么我們就設定一個全局的標志來表明發(fā)生了MarkStack OverFlow,然后我們將那些不能push入stack的OBject的bit1設定為NotYetScanned。然后當tracing過程完成以后,檢驗全局標志假如發(fā)現(xiàn)有overflow則把NotYetScanned的對象再次壓入堆棧開始新的tracing過程。
  
  并行Mark(Parallel Mark)
  
  由于使用逐位清掃(bitwise sweep)和內存緊縮規(guī)避功能,GC將化大部分的時間是用于Mark而非前面兩項。這就導致了IBM JVM需要開發(fā)一個GC的并行版本。并行GC的目的不是以犧牲單CPU系統(tǒng)上的效能來換取在4,8路對稱CPU系統(tǒng)上的高效率。
  
  并行Mark的基本思想就是通過多個輔助線程(helper thread)和一個共享工作的工具來減少Marking的時間。在單CPU系統(tǒng)中,執(zhí)行GC工作的只有一個主線程。Parallel mark仍然需要這個主線程的參與,他充當了治理協(xié)調的角色。這個Thread所要執(zhí)行的工作和單CPU上的一樣多,包括他必須掃描C-Stack來鑒別需要收集的roots指針。一個有N路對稱CPU的系統(tǒng)自動含有n-1個helper thread并且平均分布在每個CPU上,master thread將scan完的reference集合進行分塊,然后交給helper thread獨立完成mark工作。
  
  每個Helper thread都被分配了一個獨立的本地mark stack,以及一個shareable queue。sharqueue將存放help thread在mark overflow的時候的NotyetScanned對象。然后由master thread將sharequeue中的對象balance到其他已經(jīng)空閑的thread上去。
  
  并發(fā)Mark(Concurrent mark)
  
  Concurrent mark的主要目的在于當heap增長的時候減少GC的pause time。只要heap到達heap limit的時候,Concurrent mark就會被執(zhí)行。在Concurrent phase中,GC要求應用中的每個線程(不是指helper thread而是應用程序自己開啟的線程以便充分利用系統(tǒng)資源)掃描他們自己的堆棧來得到roots。然后使用這些roots來同步的trace 可達對象。Tracing工作是由一個后臺的低優(yōu)先級的線程執(zhí)行,同時程序自己開啟的線程在分配內存的時候必須執(zhí)行heap lock allocation。
  
  由于使用程序自己開啟的線程并發(fā)的執(zhí)行mark live objects,我們必須紀錄那些已經(jīng)trace過的object的變化。這個功能是采用一個叫寫閘(write barrier) 來實現(xiàn)的。這個寫閘在每次改變引用的時候被激活。它告訴我們什么時候一個對象被跟新過了,以便我們從新掃描那部分heap。寫閘的具體實現(xiàn)是Heap會分配出512byte的內存段每個段都分配了一個byte在卡表中(card table)。無論何時一個對象的reference被更新cardtable將同步紀錄這個對象的起始地址。使用Byte而不用bit的原因是寫byte要比寫bit快2倍,而且我們可能希望空余的bit會在未來被用到。
  
  當Concurrent mark執(zhí)行完畢以后,STW collection(stop total world)將會被執(zhí)行。stw的意思是指suspend所有程序自己開啟的線程。因此我們可以看到假如使用Concurrent mark那

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 免费国产 | 欧美性生活久久 | 中文字幕网址 | 国产91av视频| 蜜桃麻豆视频 | 国产做爰 | 56av国产精品久久久久久久 | 一级免费黄色免费片 | 亚洲国产综合在线观看 | 高清一区二区在线观看 | 国产精品一区二区三区在线播放 | 在线观看视频亚洲 | 黄视频网址 | 亚洲男人的天堂在线视频 | 92看片淫黄大片一级 | 中文字幕在线观看精品 | 九九热色 | h视频免费在线观看 | 国产乱乱视频 | 中文字幕专区高清在线观看 | 最新黄色毛片 | 天天躁狠狠躁夜躁2020挡不住 | 蜜桃精品视频在线观看 | 免费看国产视频 | 97干在线| 国产午夜亚洲精品理论片大丰影院 | 久久久久国产一区二区三区不卡 | 久草在线资源福利站 | 今井夏帆av一区二区 | 色妞妞视频 | 午夜国产小视频 | 免费专区 - 91爱爱 | 久久国产一二三 | av手机免费在线观看 | 国产深夜福利视频在线播放 | 国产91久久精品一区二区 | 91短视频版高清在线观看免费 | 日韩在线播放第一页 | 色啪综合| 在线亚洲欧美 | 成人黄色短视频在线观看 |