<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    qileilove

    blog已經(jīng)轉(zhuǎn)移至github,大家請?jiān)L問 http://qaseven.github.io/

    多核平臺下的Java優(yōu)化

     現(xiàn)在多核 CPU 是主流。利用多核技術(shù),可以有效發(fā)揮硬件的能力,提升吞吐量,對于 Java 程序,可以實(shí)現(xiàn)并發(fā)垃圾收集。但是 Java 利用多核技術(shù)也帶來了一些問題,主要是多線程共享內(nèi)存引起了。目前內(nèi)存和 CPU 之間的帶寬是一個(gè)主要瓶頸,每個(gè)核可以獨(dú)享一部分高速緩存,可以提高性能。JVM 是利用操作系統(tǒng)的”輕量級進(jìn)程”實(shí)現(xiàn)線程,所以線程每操作一次共享內(nèi)存,都無法在高速緩存中命中,是一次開銷較大的系統(tǒng)調(diào)用。所以區(qū)別于普通的優(yōu)化,針對多核平臺,需要進(jìn)行一些特殊的優(yōu)化。

      代碼優(yōu)化

      線程數(shù)要大于等于核數(shù)

      如果使用多線程,只有運(yùn)行的線程數(shù)比核數(shù)大,才有可能榨干 CPU 資源,否則會(huì)有若干核閑置。要注意的是,如果線程數(shù)目太多,就會(huì)占用過多內(nèi)存,導(dǎo)致性能不升反降。JVM 的垃圾回收也是需要線程的,所以這里的線程數(shù)包含 JVM 自己的線程

      盡量減少共享數(shù)據(jù)寫操作

      每個(gè)線程有自己的工作內(nèi)存,在這個(gè)區(qū)域內(nèi),系統(tǒng)可以毫無顧忌的優(yōu)化,如果去讀共享內(nèi)存區(qū)域,性能也不會(huì)下降。但是一旦線程想寫共享內(nèi)存(使用 volatile 關(guān)鍵字),就會(huì)插入很多內(nèi)存屏障操作(Memory Barrier 或者 Memory Fence)指令,保證處理器不亂序執(zhí)行。相比寫本地線程自有的變量,性能下降很多。處理方法是盡量減少共享數(shù)據(jù),這樣也符合”數(shù)據(jù)耦合”的設(shè)計(jì)原則。

      使用 synchronize 關(guān)鍵字

      在 Java1.5 中,synchronize 是性能低效的。因?yàn)檫@是一個(gè)重量級操作,需要調(diào)用操作接口,導(dǎo)致有可能加鎖消耗的系統(tǒng)時(shí)間比加鎖以外的操作還多。相比之下使用 Java 提供的 Lock 對象,性能更高一些。但是到了 Java1.6,發(fā)生了變化。synchronize 在語義上很清晰,可以進(jìn)行很多優(yōu)化,有適應(yīng)自旋,鎖消除,鎖粗化,輕量級鎖,偏向鎖等等。導(dǎo)致在 Java1.6 上 synchronize 的性能并不比 Lock 差。官方也表示,他們也更支持 synchronize,在未來的版本中還有優(yōu)化余地。

      使用樂觀策略

      傳統(tǒng)的同步并發(fā)策略是悲觀的。表現(xiàn)語義為:多線程操作一個(gè)對象的時(shí)候,總覺得會(huì)有兩個(gè)線程在同時(shí)操作,所以需要鎖起來。樂觀策略是,假設(shè)平時(shí)就一個(gè)線程訪問,當(dāng)出現(xiàn)了沖突的時(shí)候,再重試。這樣更高效一些。Java 的 AtomicInteger 就是使用了這個(gè)策略。

      使用線程本地變量(ThreadLocal)

      使用 ThreadLocal 可以生成線程本地對象的副本,不會(huì)和其他線程共享。當(dāng)該線程終止的時(shí)候,其本地變量可以全部回收。

      類中 Field 的排序

      可以將一個(gè)類會(huì)頻繁訪問到的幾個(gè) field 放在一起,這樣他們就有更多的可能性被一起加入高速緩存。同時(shí)最好把他們放在頭部?;咀兞亢鸵米兞坎灰诲e(cuò)排放。

      批量處理數(shù)組

      現(xiàn)在處理器可以用一條指令來處理一個(gè)數(shù)組中的多條記錄,例如可以同時(shí)向一個(gè) byte 數(shù)組中讀或者寫 store 記錄。所以要盡量使用 System.arraycopy ()這樣的批量接口,而不是自己操作數(shù)組。

      JVM 優(yōu)化

      啟用大內(nèi)存頁

      現(xiàn)在一個(gè)操作系統(tǒng)默認(rèn)頁是4K。如果你的 heap 是4GB,就意味著要執(zhí)行1024*1024次分配操作。所以最好能把頁調(diào)大。這個(gè)配額設(shè)計(jì)操作系統(tǒng),單改 Jvm 是不行的。Linux 上的配置有點(diǎn)復(fù)雜,不詳述。

      在 Java1.6 中 UseLargePages 是默認(rèn)開啟的,LasrgePageSzieInBytes 被設(shè)置成了4M。筆者看到一些情況下配置成了128MB,在官方的性能測試中更是配置到256MB。

      啟用壓縮指針

      Java 的64的性能比32慢,原因是因?yàn)槠渲羔樣?2位擴(kuò)展到64位,雖然尋址空間從4GB 擴(kuò)大到 256 TB,但導(dǎo)致性能的下降,并占用了更多的內(nèi)存。所以對指針進(jìn)行壓縮。壓縮后的指針最多支持32GB 內(nèi)存,并且可以獲得32位 JVM 的性能。

      在 JDK6 update 23 默認(rèn)開啟了,之前的版本可以使用-XX:+UseCompressedOops 來啟動(dòng)配置。

      性能可以看這個(gè)評測,性能的提升是很可觀。


    啟用 NUMA

      numa 是一個(gè) CPU 的特性。SMP 架構(gòu)下,CPU 的核是對稱,但是他們共享一條系統(tǒng)總線。所以 CPU 多了,總線就會(huì)成為瓶頸。在 NUMA 架構(gòu)下,若干 CPU 組成一個(gè)組,組之間有點(diǎn)對點(diǎn)的通訊,相互獨(dú)立。啟動(dòng)它可以提高性能。

      NUMA 需要硬件,操作系統(tǒng),JVM 同時(shí)啟用,才能啟用。Linux 可以用 numactl 來配置 numa,JVM 通過-XX:+UseNUMA 來啟用。

      激進(jìn)優(yōu)化特性

      在 Java1.6 中,激進(jìn)優(yōu)化(AggressiveOpts)是默認(rèn)開啟的。激進(jìn)優(yōu)化是一般有一些下一個(gè)版本才會(huì)發(fā)布的優(yōu)化選項(xiàng)。但是有可能造成不穩(wěn)定。前段時(shí)間以訛傳訛的 JDK7的 Bug,就是開啟這個(gè)選項(xiàng)后測到的。

      逃逸分析

      讓一個(gè)對象在一個(gè)方法內(nèi)創(chuàng)建后,如果他傳遞出去,就可以稱為方法逃逸;如果傳遞到別的線程,成為線程逃逸。如果能知道一個(gè)對象沒有逃逸,就可以把它分配在棧而不是堆上,節(jié)約 GC 的時(shí)間。同時(shí)可以將這個(gè)對象拆散,直接使用其成員變量,有利于利用高速緩存。如果一個(gè)對象沒有線程逃逸,就可以取消其中一切同步操作,很大的提高性能。

      但是逃逸分析是很有難度的,因?yàn)榛?cpu 去對一個(gè)對象去分析,要是他不逃逸,就無法優(yōu)化,之前的分析血本無歸。所以不能使用復(fù)雜的算法,同時(shí)現(xiàn)在的 JVM 也沒有實(shí)現(xiàn)棧上分配。所以開啟之后,性能也可能下降。

      可以使用-XX:+DoEscapeAnalysis 來開啟逃逸分析。

      高吞吐量 GC 配置

      對于高吞吐量,在年輕態(tài)可以使用 Parallel Scavenge,年老態(tài)可以使用 Parallel Old 垃圾收集器。

      使用-XX:+UseParallelOldGC 開啟

      可以將-XX:ParallelGCThreads 根據(jù) CPU 的個(gè)數(shù)進(jìn)行調(diào)整??梢允?CPU 數(shù)的1/2或者5/8

      低延遲 GC 配置

      對于低延遲的應(yīng)用,在年輕態(tài)可以使用 ParNew,年老態(tài)可以使用 CMS 垃圾收集器。

      可以使用-XX:+UseConcMarkSweepGC 和-XX:+UseParNewGC 打開。

      可以將-XX:ParallelGCThreads 根據(jù) CPU 的個(gè)數(shù)進(jìn)行調(diào)整??梢允?CPU 數(shù)的1/2或者5/8

      可以調(diào)整-XX:MaxTenuringThreshold (晉升年老代年齡)調(diào)高,默認(rèn)是15.這樣可以減少年老代 GC 的壓力

      可以-XX:TargetSurvivorRatio,調(diào)整 Survivor 的占用比率。默認(rèn)50%.調(diào)高可以提供 Survivor 區(qū)的利用率

      可以調(diào)整-XX:SurvivorRatio,調(diào)整 Eden 和 Survivor 的比重。默認(rèn)是8。這個(gè)比重越小,Survivor 越大,對象可以在年輕態(tài)呆更多時(shí)間。

    posted on 2011-11-15 14:34 順其自然EVO 閱讀(169) 評論(0)  編輯  收藏 所屬分類: 測試學(xué)習(xí)專欄

    <2011年11月>
    303112345
    6789101112
    13141516171819
    20212223242526
    27282930123
    45678910

    導(dǎo)航

    統(tǒng)計(jì)

    常用鏈接

    留言簿(55)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲国产精品成人午夜在线观看| 亚洲中文字幕在线第六区| 好猛好深好爽好硬免费视频| 亚洲午夜电影在线观看| 亚洲国产天堂久久久久久| 成人女人A级毛片免费软件| caoporm超免费公开视频| 亚洲高清乱码午夜电影网| 亚洲精品资源在线| 亚洲gv白嫩小受在线观看| 亚洲男人在线无码视频| sss在线观看免费高清| 免费视频精品一区二区| 亚洲高清毛片一区二区| 激情五月亚洲色图| 亚洲av午夜精品无码专区| 亚洲成人免费电影| 亚洲午夜一区二区电影院| 激情内射亚洲一区二区三区| 日本亚洲国产一区二区三区| 区三区激情福利综合中文字幕在线一区亚洲视频1| 97无码免费人妻超级碰碰碰碰| 在线观看H网址免费入口| 99re在线这里只有精品免费| 日韩免费人妻AV无码专区蜜桃| 无码av免费一区二区三区| 最近免费最新高清中文字幕韩国 | 大地资源免费更新在线播放| 国产91色综合久久免费| 18禁无遮挡无码网站免费| 日本一线a视频免费观看| 免费观看四虎精品国产永久| 久久久亚洲精品蜜桃臀| 亚洲国产精品无码专区| 亚洲精品欧洲精品| 婷婷亚洲天堂影院| 777成影片免费观看| 亚洲综合中文字幕无线码| 可以免费观看的一级毛片| 亚洲avav天堂av在线网爱情| 亚洲一区二区三区在线网站|