記一次idea性能調優


  因自研的自動化測試工具包含壓測功能,在自己本地代碼開發完畢后進行測試,對目標接口進行1000次訪問,發現idea在執行結束后變的異常卡頓,懷疑是idea工具或者程序代碼存在問題,遂進行排查。
----------------------------------------------------------------------------------------------
  本地所用MacBook Pro 2015配置
  處理器:i7 2.2GHz
  核心數:4
  內存:16GB
  系統:macOS Mojave
----------------------------------------------------------------------------------------------
  先從idea排查開始:
   1、打開jdk自帶的jconsole工具,連接idea;同時打開活動監控器
  啟動idea,可以看到idea的cpu跟內存消耗並不高:

  啟動程序,再次觀察cpu跟內存,cpu從2%到了10%,內存增長300M:

  本以為jconsole能明顯看到jvm的變化情況,結果不然,而且顯示的數值很小,只有47兆:

  這跟系統的活動監視器的結果明顯不符合嘛,后來發現,jconsole實際把idea跟程序的jvm內存使用都分開了,這個顯示的只是idea的,其實本例中如果要查看內存大小,應該直接監控程序的。這個是程序的執行模塊的內存情況:
   2、執行壓測程序,1000訪問量,第一次執行
  idea變得非常卡頓,系統的監控器看到明顯的內存變化:
  同時,jconsole看到了明顯的內存跟cpu變化情況:
  堆中老年代old:62M,新生代eden:780M左右,幸存區15M,之所以看到新生代跟幸存區一樣高,是因為這里顯示的百分比,實際新生代占用的非常多。這里多說一句,jvm的各個區的命名也是挺有意思的,新對象剛出生,就叫eden區,eden,,,伊甸園么,亞當跟夏娃開始的那個地方,這名字挺合適的;然后會有垃圾收集,挺不過去就被回收了,對對象來說這輩子也就算完了,挺過去的話,這條命算是保住了,屬於幸存者,於是到了幸存區(survivor)。可是生活並沒有結束,接下來還是有一次次的gc來考驗我們的對象,很多人沒能堅持下來,最終經歷15次gc而沒被回收的,相對來說年齡也不小了,進入的區域叫老年代(old)。挺有意思。
這次執行結束之后,idea的響應速度還是可以的,不是怎么卡頓。
   3、壓測1000訪問量,第二次
  從之前的經歷來看,就是這次壓測會導致idea非常卡頓,監控器情況:
  執行過程中跟上次相比,並無明顯區別,cpu跟內存均沒有明顯增長,但idea拋出了OOM提示框:
  如果修改這幾個參數,修改后的內容將被保存到/Users/nm/Library/Preferences/IntelliJIdea2018/idea.vmoptions中,idea默認讀的配置文件也是這個,而不是安裝目錄的bin下的。
  壓測程序執行結束之后,監控器看到的idea占用cpu依然很高,對idea的操作也會有卡頓(有時比較明顯,也偶爾有相對流暢的):
 
  點擊Memory Dump,信息會被存到idea.vmoptions,然后點擊continue繼續。
  jconsole同樣看到了內存跟cpu的增長:
  圖表中的15:54左右的內存下降應該是jvm的gc導致,后邊16:10分左右的cpu跟內存暴增然后降低才是這次壓測的表現。(為何堆內存在16:10會驟降,懷疑可能正好有一次gc,jconsole的vm概要有gc次數,忘了截圖)
  idea OOM框dump出的信息保存在$USER_HOME/heapDump_Leak_Supports.zip中,解壓有heapDump.hprof文件,內容如下:
  用Memory Analyzer Tool打開這個hprof進行查看:
  說是a、b兩部分內容“懷疑有罪”,分別235M跟109M,這兩個都是什么東西呢?
  兩個都是idea自己的一個類的對象com.intellij.openapi.editor.impl.DocumentImpl,看名字是個文檔實現類
  到這里,其實我已經猜出問題出在哪里了,是日志!因為我以前把控制台的輸出設置為無限制,而為了本地調試方便,我又把hibernate的日志也打印了出來,在執行單個案例的時候並不明顯,而如果執行大量案例執行,這個日志的量就非常大了,多次壓測1000訪問量后系統產生大量日志,這些日志都被作為文本類的內容被保存了起來,又因為我把控制台日志設為無限,idea不清除這些類對象,最終導致對象越來越大,拖垮了idea。
  如果檢測的不是idea而是自己的程序,那么還可以繼續通過histogram跟dominator_tree進行跟蹤。因為強引用、軟引用、弱引用跟虛引用只有強引用不會被gc,如果多次gc沒有回收掉,肯定有強引用在關聯這個對象,通過支配樹  dominator_tree(展示對象層級關系跟內存占用百分比)跟Merge Shortest Paths to GC Roots(展示gc樹引用關系圖)可以慢慢找到強引用的所在,從而定位內存溢出原因。
  定位了問題后,稍后又對idea的各個參數進行了一次調整,因為默認的配置相對來說低了點,參考: https://segmentfault.com/a/1190000010144588
   4、參數修正
  明白了問題所在,那么進行修復並測試,修改idea的相關參數配置為:
-Xms512m
-Xmn512m
-Xmx2048m
-XX:ReservedCodeCacheSize=240m
-XX:+UseCompressedOops
-Dfile.encoding=UTF-8
-XX:+UseG1GC   //使用G1收集器,好處是並行收集
-XX:+UseNUMA  //優先使用速度較快的內存
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-Djdk.http.auth.tunneling.disabledSchemes=""
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow
-Xverify:none

-XX:ErrorFile=$USER_HOME/java_error_in_idea_%p.log
-XX:HeapDumpPath=$USER_HOME/java_error_in_idea.hprof
-javaagent:JetbrainsCrack-3.1-release-enc.jar
  主要是將堆內存最小設為512,最大為2G,變為了原來的3倍,然后把gc算法改為了G1,並優化內存讀取為NUMA。NUMA我也不熟悉,網上查到的結果如下:
  numa 是一個 CPU 的特性。SMP 架構下,CPU 的核是對稱,但是他們共享一條系統總線。所以 CPU 多了,總線就會成為瓶頸。在 NUMA 架構下,若干 CPU 組成一個組,組之間有點對點的通訊,相互獨立。啟動它可以提高性能。
  NUMA 需要硬件,操作系統,JVM 同時啟用,才能啟用。Linux 可以用  numactl 來配置 numa,JVM 通過-XX:+UseNUMA來啟用。
   5、執行,查看結果
  按照以上步驟,同樣程序啟動后執行兩次請求數量均為1000的壓測,jconsole如圖:
  兩次明顯的內存增長跟cpu消耗,監控器看到的內存情況:
  相比之前,idea的內存增長到了2.5G,cpu在壓測結束后恢復正常。點擊idea使用,沒有在發生卡頓的情況,可知的確是日志導致idea卡頓的。而當時idea的cpu消耗亦很高,應該是頻繁gc所致。
  當然,我僅僅這么修改是肯定不行的,如果控制台仍舊是無限,那么總有一天還是會oom的,我目前是手動清空控制台,發現效果也還可以,會有效。如果不手動清空,則一定要設置控制台最大行數,或者內存值,防止因日志而導致的idea卡死現象。
--------------------------------------------------------------------------
  對jconsole的使用並不熟練,如有錯誤之處請留言指正,多謝多謝。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM