天天看點

多核平台下的Java優化

  代碼優化

  線程數要大于等于核數

  如果使用多線程,隻有運作的線程數比核數大,才有可能榨幹 cpu 資源,否則會有若幹核閑置。要注意的是,如果線程數目太多,就會占用過多記憶體,導緻性能不升反降。jvm 的垃圾回收也是需要線程的,是以這裡的線程數包含 jvm 自己的線程

  盡量減少共享資料寫操作

  使用 synchronize 關鍵字

  在 java1.5 中,synchronize 是性能低效的。因為這是一個重量級操作,需要調用操作接口,導緻有可能加鎖消耗的系統時間比加鎖以外的操作還多。相比之下使用 java 提供的 lock 對象,性能更高一些。但是到了 java1.6,發生了變化。synchronize 在語義上很清晰,可以進行很多優化,有适應自旋,鎖消除,鎖粗化,輕量級鎖,偏向鎖等等。導緻在 java1.6 上 synchronize 的性能并不比 lock 差。官方也表示,他們也更支援 synchronize,在未來的版本中還有優化餘地。

  使用樂觀政策

  傳統的同步并發政策是悲觀的。表現語義為:多線程操作一個對象的時候,總覺得會有兩個線程在同時操作,是以需要鎖起來。樂觀政策是,假設平時就一個線程通路,當出現了沖突的時候,再重試。這樣更高效一些。java 的 atomicinteger 就是使用了這個政策。

  使用線程本地變量(threadlocal)

  類中 field 的排序

  可以将一個類會頻繁通路到的幾個 field 放在一起,這樣他們就有更多的可能性被一起加入高速緩存。同時最好把他們放在頭部。基本變量和引用變量不要交錯排放。

  批量處理數組

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

  jvm 優化

  啟用大記憶體頁

  啟用壓縮指針

  java 的64的性能比32慢,原因是因為其指針由32位擴充到64位,雖然尋址空間從4gb 擴大到 256 tb,但導緻性能的下降,并占用了更多的記憶體。是以對指針進行壓縮。壓縮後的指針最多支援32gb 記憶體,并且可以獲得32位 jvm 的性能。

  在 jdk6 update 23 預設開啟了,之前的版本可以使用-xx:+usecompressedoops 來啟動配置。

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

多核平台下的Java優化

<a href="http://www.51testing.com/batch.download.php?aid=29120" target="_blank">啟用 numa</a>

<a href="http://www.51testing.com/batch.download.php?aid=29120" target="_blank">  numa 是一個 cpu 的特性。smp 架構下,cpu 的核是對稱,但是他們共享一條系統總線。是以 cpu 多了,總線就會成為瓶頸。在 numa 架構下,若幹 cpu 組成一個組,組之間有點對點的通訊,互相獨立。啟動它可以提高性能。</a>

<a href="http://www.51testing.com/batch.download.php?aid=29120" target="_blank">  numa 需要硬體,作業系統,jvm 同時啟用,才能啟用。linux 可以用 numactl 來配置 numa,jvm 通過-xx:+usenuma 來啟用。</a>

<a href="http://www.51testing.com/batch.download.php?aid=29120" target="_blank">  激進優化特性</a>

<a href="http://www.51testing.com/batch.download.php?aid=29120" target="_blank">  在 java1.6 中,激進優化(aggressiveopts)是預設開啟的。激進優化是一般有一些下一個版本才會釋出的優化選項。但是有可能造成不穩定。前段時間以訛傳訛的 jdk7的 bug,就是開啟這個選項後測到的。</a>

<a href="http://www.51testing.com/batch.download.php?aid=29120" target="_blank">  逃逸分析</a>

<a href="http://www.51testing.com/batch.download.php?aid=29120" target="_blank">  讓一個對象在一個方法内建立後,如果他傳遞出去,就可以稱為方法逃逸;如果傳遞到别的線程,成為線程逃逸。如果能知道一個對象沒有逃逸,就可以把它配置設定在棧而不是堆上,節約 gc 的時間。同時可以将這個對象拆散,直接使用其成員變量,有利于利用高速緩存。如果一個對象沒有線程逃逸,就可以取消其中一切同步操作,很大的提高性能。</a>

<a href="http://www.51testing.com/batch.download.php?aid=29120" target="_blank">  但是逃逸分析是很有難度的,因為花了 cpu 去對一個對象去分析,要是他不逃逸,就無法優化,之前的分析血本無歸。是以不能使用複雜的算法,同時現在的 jvm 也沒有實作棧上配置設定。是以開啟之後,性能也可能下降。</a>

<a href="http://www.51testing.com/batch.download.php?aid=29120" target="_blank">  可以使用-xx:+doescapeanalysis 來開啟逃逸分析。</a>

<a href="http://www.51testing.com/batch.download.php?aid=29120" target="_blank">  高吞吐量 gc 配置</a>

<a href="http://www.51testing.com/batch.download.php?aid=29120" target="_blank">  對于高吞吐量,在年輕态可以使用 parallel scavenge,年老态可以使用 parallel old 垃圾收集器。</a>

<a href="http://www.51testing.com/batch.download.php?aid=29120" target="_blank">  使用-xx:+useparalleloldgc 開啟</a>

<a href="http://www.51testing.com/batch.download.php?aid=29120" target="_blank">  可以将-xx:parallelgcthreads 根據 cpu 的個數進行調整。可以是 cpu 數的1/2或者5/8</a>

<a href="http://www.51testing.com/batch.download.php?aid=29120" target="_blank">  低延遲 gc 配置</a>

<a href="http://www.51testing.com/batch.download.php?aid=29120" target="_blank">  對于低延遲的應用,在年輕态可以使用 parnew,年老态可以使用 cms 垃圾收集器。</a>

<a href="http://www.51testing.com/batch.download.php?aid=29120" target="_blank">  可以使用-xx:+useconcmarksweepgc 和-xx:+useparnewgc 打開。</a>

<a href="http://www.51testing.com/batch.download.php?aid=29120" target="_blank">  可以調整-xx:maxtenuringthreshold (晉升年老代年齡)調高,預設是15.這樣可以減少年老代 gc 的壓力</a>

<a href="http://www.51testing.com/batch.download.php?aid=29120" target="_blank">  可以-xx:targetsurvivorratio,調整 survivor 的占用比率。預設50%.調高可以提供 survivor 區的使用率</a>

<a href="http://www.51testing.com/batch.download.php?aid=29120" target="_blank">  可以調整-xx:survivorratio,調整 eden 和 survivor 的比重。預設是8。這個比重越小,survivor 越大,對象可以在年輕态呆更多時間。</a>

本文出自seven的測試人生公衆号最新内容請見作者的github頁:http://qaseven.github.io/