乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      JVM的GC調(diào)優(yōu)

       dongsibei 2014-04-23

      誰(shuí)需要GC調(diào)優(yōu)

      小規(guī)模程序,垃圾收集算法能很好的工作。因?yàn)槔锩娴膶?duì)象圖不大,所以收集代價(jià)不高。但是如果是大規(guī)模的程序,對(duì)象成百上千,一次遍歷,就算是復(fù)制收集器中只對(duì)活動(dòng)對(duì)象的遍歷,都需要很長(zhǎng)的時(shí)間。所以,大規(guī)模程序,有必要深入了解GC的工作方式,了解和調(diào)整GC的參數(shù)。

      關(guān)于串行和并行GC收集算法

      在JVM 1.3.1以前,只有串行收集器,沒(méi)有并行收集器,對(duì)于多處理器,系統(tǒng)吞吐量損失很大。見(jiàn)下圖。為此,1.3.1以后(不包含1.3.1),引入了并發(fā)GC收集算法。
      JVM1.4.2上,有4種垃圾收集器,默認(rèn)會(huì)選擇串行收集器。
      JVM5.0后,則會(huì)根據(jù)用戶機(jī)器的類(lèi)型自動(dòng)選擇收集器。

      1% GC 中的 1%是指,在一個(gè)CPU上執(zhí)行且只花1%的CPU時(shí)間做垃圾收集的應(yīng)用程序。
      可以看到,當(dāng)這個(gè)程序在處理器為30個(gè)以上的系統(tǒng)上運(yùn)行,系統(tǒng)的吞吐量會(huì)下降到80%以下,即本來(lái)在單CPU系統(tǒng)上只花1%時(shí)間做搜集的程序會(huì)在30個(gè)以上CPU的系統(tǒng)上,花上20%的時(shí)間做收集。

      為什么會(huì)這樣呢?因?yàn)閱蜟PU收集算法在多CPU系統(tǒng)上面做收集的時(shí)候,GC算法會(huì)暫停運(yùn)行在任何CPU上面的程序,而自己卻只能利用一個(gè)CPU做GC,所以造成了這種情況。

      代Generation

      自從JVM1.2以后,Sun采用了一種分代收集的策略,即將堆分成3個(gè)不同的區(qū)域,按照對(duì)象存活的時(shí)間的不同,將對(duì)象保存在不同的堆上。在不同的代上面,應(yīng)用不同的收集算法,來(lái)達(dá)到最優(yōu)化收集。

      這3個(gè)區(qū)域叫年輕代,年老代和持久代。
      除Class和Method等元數(shù)據(jù)在持久代上面分配以外,所有的對(duì)象都在年輕代上面分配,當(dāng)達(dá)到一定的條件,如經(jīng)過(guò)在年輕代上面N次收集后的對(duì)象,就會(huì)保存到年老代之中。

      在年輕代上面進(jìn)行的收集叫Minor collections,在年輕代和年老代上面同時(shí)收集叫Major collections。

      Tips:

      盡量不要調(diào)用System.gc(),因?yàn)檫@會(huì)觸發(fā)Major collections。Major collections的收集效率不高,因?yàn)樗闅v幾乎所有的對(duì)象。
      沒(méi)有辦法利用API直接觸發(fā)Minor collections,但是仍然有其他的調(diào)優(yōu)手段。當(dāng)使用完集合對(duì)象后,把引用設(shè)置為null,這樣避免gc在收集過(guò)程中,無(wú)謂地遍歷那些即將就要釋放的對(duì)象。

      實(shí)驗(yàn)表明,年輕代上面的對(duì)象98%的對(duì)象都會(huì)在短時(shí)間內(nèi)死亡,故Minor collections可以利用拷貝收集器,只遍歷那些2%存活的對(duì)象,而不用管那些死亡的對(duì)象,來(lái)提高收集效率。

      為了讓Minor collections能充分利用年輕代上面對(duì)象大量死亡的這個(gè)特點(diǎn),就需要調(diào)整以下幾個(gè)參數(shù):
      1. 收集的頻率
      過(guò)于頻繁的收集,會(huì)導(dǎo)致代中對(duì)象死亡率不夠高,從而需要遍歷這個(gè)代中大部分的對(duì)象,使得高死亡率這個(gè)條件利用的不充分。

      2. 年輕代(堆)的大小
      如果堆太小,一旦堆被占滿,Minor collections就不得不頻繁的啟動(dòng),導(dǎo)致情況1的發(fā)生,從而降低收集效率。

      下圖反應(yīng)了絕大多數(shù)對(duì)象在早起死亡的這一個(gè)事實(shí):

      從圖中可以看到,隨著時(shí)間的推進(jìn),大部分分配的字節(jié)都被回收了,少部分留了下來(lái)。被回收的這些字節(jié),就是所謂的die young,留下的則是live longer。

      Bytes allocated 已經(jīng)分配的總字節(jié)數(shù)
      Bytes Surviving 存活的字節(jié)數(shù)
      Minor Collections 對(duì)年輕代進(jìn)行收集
      Major Collections 對(duì)所有代進(jìn)行收集

      下圖描述了JVM中對(duì)堆的劃分:

      Young 年輕代
      Tenured 年老代
      Perm 持久代

      Virutal是指保留,而未分配的內(nèi)存。如Perm中,加上Virtual則是Perm區(qū)域最大的大小,而剛開(kāi)始并不會(huì)完全分配這個(gè)堆,只會(huì)按照最小的大小分配。

      Young部分,被分為了三個(gè)部分,一個(gè)Eden,和兩個(gè)大小相同的Survivor。
      所有的新建對(duì)象都會(huì)在Eden中分配,當(dāng)Eden占滿后,即剩余的大小不足以分配新的對(duì)象時(shí),就會(huì)觸發(fā)Minor collections。對(duì)Young收集時(shí),會(huì)將對(duì)象拷貝到其中一個(gè)Survivor,另外一個(gè)Survivor保留不用。當(dāng)下次收集時(shí),則將上次Survivor中和Eden中的活動(dòng)對(duì)象,拷貝到未用的Survivor中。如此反復(fù)。當(dāng)某些對(duì)象經(jīng)歷足夠長(zhǎng)的次數(shù)或者時(shí)間后,就會(huì)被拷貝入年老代。

      如果對(duì)Young的minor collections收集到的活動(dòng)對(duì)象,survivor無(wú)法完全容納,則會(huì)將某些對(duì)象拷貝到年老代,如果年老代也不能容納新拷貝入的對(duì)象,則觸發(fā)Major collections。如果Major collections后,如果還不足以容納,就會(huì)將Virutal中預(yù)留的空間用來(lái)擴(kuò)展已有的堆。當(dāng)保留Virutal分配完畢后,仍然不足時(shí),就會(huì)拋出OutOfMemory的錯(cuò)誤。

      Tips:

      不要把年老代設(shè)置的過(guò)小,一般最好能比eden+survivor更大一些,這樣可以避免觸發(fā)Major collections。在這個(gè)前提下,年輕代越大越好。由于Young的eden區(qū)域是拷貝收集,容易產(chǎn)生碎片,所以此區(qū)域越大,越不容易導(dǎo)致因?yàn)樗槠瑢?dǎo)致的內(nèi)存不足而引發(fā)的minor collections。至于survivor,則要根據(jù)情況調(diào)整。過(guò)大的survior會(huì)造成浪費(fèi),過(guò)小的survior會(huì)導(dǎo)致,對(duì)象被直接拷貝到年老代。

      JVM1.2中,未使用上面一大二小的結(jié)構(gòu),而是將Young分成兩個(gè)相同大小的區(qū)域,來(lái)回進(jìn)行拷貝。

      調(diào)整GC的手段


      如何看懂上面那張圖:

      行,分別對(duì)應(yīng)了三個(gè)代
      列,分別對(duì)應(yīng)了實(shí)時(shí)性要求比較高的默認(rèn)的和可調(diào)節(jié)的選項(xiàng), 以及對(duì)吞吐量比較高的默認(rèn)的和可調(diào)節(jié)的選項(xiàng),還有就是調(diào)整這3個(gè)堆的選項(xiàng)。

      -Xmx 調(diào)整JVM啟動(dòng)時(shí),保留Total Size的大小
      -Xms 調(diào)整JVM啟動(dòng)初始化時(shí),Total Size的大小

      每一次收集后,都會(huì)根據(jù)以下兩個(gè)參數(shù)調(diào)整Total Size的大小

      -XX:MinHeapFreeRatio(默認(rèn),40)     Total Size中可用空間小于這個(gè)比率,就會(huì)擴(kuò)展堆的大小,保持這個(gè)值
      -XX:MaxHeapFreeRatio(默認(rèn),70)     Total Size中可用空間大于這個(gè)比例,就縮小堆的大小,保持這個(gè)值

      Tips:

      如果你的程序是服務(wù)器,那么通過(guò)將-Xmx和-Xms設(shè)置成相近,或者相同,可以阻止這種堆大小的頻繁調(diào)整,造成的不必要的收集和堆增長(zhǎng)過(guò)程。

      -XX:NewRatio=3     年老代和年輕代的內(nèi)存分配比率,3表示,在Total Size中,年輕代占1份,年老代3份
      -XX:NewSize           年輕代初始化時(shí)的大小
      -XX:MaxNewSize     如果不指定,那么年輕代可以增長(zhǎng)不受限制,但受NewRatio的限制
      -XX:SurvivorRato=6 年輕代中,eden與survivor的比率,這里eden占6份,2個(gè)survivor占2份
      -XX:MaxTenuringThreshold=0 閥值,超過(guò)這個(gè)閥值的對(duì)象將被拷貝到年老代

      如何進(jìn)行GC調(diào)優(yōu)?

      1.性能的幾個(gè)重要度量參數(shù)

      Troughput     吞吐量,除掉GC所用的時(shí)間后,真正執(zhí)行程序所在總時(shí)間的百分比
      Pauses          暫停時(shí)間,即由于正在做GC,而沒(méi)有響應(yīng)的那些時(shí)間
      Footprint        內(nèi)存需求,通常用page和cache line的數(shù)量來(lái)衡量

      2.查看當(dāng)前的GC收集

      java命令運(yùn)行時(shí),輸入 -verbose:gc 參數(shù)

      [GC 4802K->4383K(5312K), 0.0078566 secs]         //執(zhí)行了Minor collections
      [Full GC 4383K->4383K(5312K), 0.0385521 secs]   //執(zhí)行了Major collections
      [GC 5248K->4814K(8216K), 0.0121798 secs]         //空間仍然不夠,擴(kuò)展了年輕代和年老代的空間

      以第一行為例

      GC                       表示執(zhí)行了Minor collections
      4802K->4383K    表示GC執(zhí)行前和執(zhí)行后,堆中活動(dòng)對(duì)象的大小
      (5312K)               表示總的堆的大小(不算持久代,而且只算2個(gè)Survivor中的1個(gè),即用戶可用堆的大?。?br>0.0078566 secs   表示GC所用的時(shí)間。主要,也是首先看這個(gè),然后再看GC/Full GC是否過(guò)于頻繁。

      這個(gè)信息反應(yīng)了什么?年輕代太小,因?yàn)閳?zhí)行了Minor collections之后,活動(dòng)的對(duì)象并沒(méi)有顯著減少,4802K->4383K, 說(shuō)明初始堆分配的不夠大。這個(gè)GC顯然是因?yàn)閑den內(nèi)部碎片導(dǎo)致的。

      用-XX:+PrintGCDetails 參數(shù),打印更詳細(xì)的信息

      [GC [DefNew: 64575K->959K(64576K), 0.0457646 secs] 196016K->133633K(261184K), 0.0459067 secs]]

      // Minor collections從年輕代64575K中收集到了959K的活動(dòng)對(duì)象,花費(fèi)了4微秒多一點(diǎn)
      DefNew: 64575K->959K(64576K), 0.0457646 secs

      //整個(gè)堆整理后,從196016K中,收集到了133633K的活動(dòng)對(duì)象
      196016K->133633K(261184K)

      還可以用-XX:+PrintGCTimeStamps 查看帶起始和終止時(shí)間戳的信息

      還有-XX:-PrintTenuringDistribution   打印出對(duì)象在放入年老代之前在年輕代做了多少次復(fù)制,如果復(fù)制次數(shù)過(guò)少,說(shuō)明年輕代過(guò)小。

      2類(lèi)收集器

      The Throughput Collector       以提高吞吐量,降低GC時(shí)間比的收集策略
      The Concurrent Low Pause Collector      以提高暫停時(shí)間,以實(shí)時(shí)性為目的的收集策略

      具體請(qǐng)看資料[1]中的內(nèi)容。

      其他

      關(guān)于,如何遍歷年輕代中的活動(dòng)對(duì)象的技術(shù),請(qǐng)看資料[3]。

      參考資料:

      1.Tuning Garbage Collection with the 5.0 Java[tm] Virtual Machine
      http://java./docs/hotspot/gc5.0/gc_tuning_5.html

      2.Garbage Collector Ergonomics
      http://java./j2se/1.5.0/docs/guide/vm/gc-ergonomics.html

      3.JVM1.4.1中的垃圾收集
      http://www.ibm.com/developerworks/cn/java/j-jtp11253/

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(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)論公約

        類(lèi)似文章 更多