如何快速、低成本、低擾動地執行一段Java程式碼
JVM是個執行服務端應用的好VM,但如果你只是想頻繁地執行一段Java寫的指令碼,或者在跑一些輔助性的Java程式比如監控,比如日誌收集,這時候的訴求就和平日裡的應用不一樣了:
1.啟動快速,動靜小。
2.低成本,節約CPU、記憶體和執行緒。
3.低擾動,不干擾主應用的執行。
一、從失敗的取經開始
第一時間,看看jmap,jstack們用了什麼引數,結果發現通通只有一個-Xms8m (在它們執行時,跑jps -v 可見,原始碼級確認JDK7見Makefile.launcher,JDK8見CompileLaunchers.gmk)。
另外,傳說中的-client,在多核的Linux伺服器上的也是無效的。
下面開始自己的折騰,首先給跑的指令碼配上"-Xloggc:gc.log
-XX:+PrintGCDetails -XX:+PrintGCDateStamps
-XX:+PrintGCApplicationStoppedTime", 在gc.log 裡就會有實際啟動引數,GC日誌,以及結束時列印記憶體各代的佔用。
其次,長期跑一個 pidstat -l 1| grep XXX 監控程式的CPU消耗
最後,jstack一下程式,看看裡面跑著多少執行緒,一個預設的JVM,執行緒數多得嚇人。
二、類的載入和編譯
1 -Xverify:none
來自最佳化Eclipse啟動速度的經驗,說關閉Java類載入驗證可以加快10% -15%的啟動速度。
2 設定編譯級別
JIT編譯之後的程式碼比解釋執行位元組碼更快,更省CPU,但編譯本身就需要CPU,也需要額外的編譯執行緒。臨時給啟動指令碼配上 “-XX:+PrintCompilation”,觀察編譯情況。
如果指令碼的程式碼只簡單的跑一次,比如vjtools裡的vjmxcli,建議就不要進行JIT編譯了,編譯完了也用不上,直接解釋執行就好。禁止它:-Djava.compiler=NONE
如果指令碼會用於迴圈計算,比如vjtools裡的vjmap,則建議開啟多層編譯,一開始就對執行到的方法進行靜態編譯,不用等方法被呼叫1萬次。多層編譯在JDK8預設開啟,顯式開啟:-XX:+TieredCompilation。
但開啟多層編譯也會導致程式執行初期有較多的編譯任務,吃比較多的CPU,可以顯式關掉多層編譯 -XX:-TieredCompilation來對比一下,綜合其帶來的效能提升,指令碼的生命週期長短,以及額外的CPU支出來綜合評價。
3 編譯執行緒的設定
在24核伺服器上,預設有4條C1編譯執行緒,8條C2編譯執行緒(多層編譯下),考慮到低成本原則,建議把它設到最小的-XX:CICompilerCount=2。
4 未來黑科技-AOT
JIT不夠酷,預先把程式碼編譯(Ahead-of-Time,AOT) 更好。 JDK9裡有一個Hotspot編譯器組搞的試驗性的jaotc,另一個選擇是GraalVM全家桶裡帶的 SubstrateVM ,這個支援JDK8。兩者都是基於Graal,看各位大大炫,但我還沒玩過。
三、GC 設定
這些指令碼,輔助程式一般不介意GC延時,建議使用吞度量最的序列收集演算法 -XX:+UseSerialGC,大大減少了其他GC演算法所產生的大量GC執行緒,保證自己GC時也不會影響到主應用。
如果依然想使用並行演算法,就一定要設定GC執行緒數,如果按預設值,在24核機器上YGC和CMS GC的執行緒數分別是18和5,一旦發生GC,將佔用大量的CPU核,直接對主應用產生巨大的影響。可設為-XX arallelGCThreads=2 -XX:ConcGCThreads=1
四、記憶體設定
JVM的堆記憶體擴張並沒有想象中那麼智慧,當-Xms 與 -Xmx 不等,又沒有指定新生代比例時,新生代大小更是混亂。建議根據執行後的實際佔用及GC日誌,完整設定一個最合適的值。
快速執行一次的指令碼,老生代幾乎沒用,新生代可以設大些。
-Xms96m -Xmx96m -Xmn64m
長期執行的,則一般設為1:1。
-Xms256m -Xmx256m -XX:NewRatio=1
每條執行緒的記憶體從預設1M回到256k:-xss256k
永久代也可以一設,可惜JDK7/8的引數不相容,用java -version 拿版本號太貴了,所以如果明確了JDK版本的話可以設定,否則就算了。
作者:Java網際網路架構師
連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2331/viewspace-2817531/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 如何在Python退出時強制執行一段程式碼Python
- **java設定一段程式碼執行超時時間(轉)**Java
- 寫一段java程式來執行linux命令JavaLinux
- 低程式碼低成本快速整合OA/ERP/MES系統 ——下秒資料
- 低程式碼如何快速提升客戶體驗
- oracle執行java程式碼OracleJava
- 如何成功地過渡到低程式碼平臺?
- 低程式碼行業未來如何?行業
- 低程式碼如何推動自動化未來
- 低程式碼行業深度如何?此文來探究!行業
- Java知識點總結(動態執行JS程式碼 )JavaJS
- 小白如何低成本快速pc站+手機站+小程式?
- 智慧移動機器人如何快速低成本構建?機器人
- 如何寫一段死鎖程式碼
- 多執行緒程式是如何執行程式碼的?執行緒行程
- 動態執行c#程式碼C#
- jexl2 執行字串Java程式碼字串Java
- 低程式碼快速搭建完整商品列表頁
- 如何用iPad執行Python程式碼?iPadPython
- Mars如何分散式地執行分散式
- 動手動腦(執行程式碼TestDouble.java)行程Java
- GraalVM 21.0提供執行Java程式碼的第三種方式:Espresso通過Truffle框架執行Java程式碼 - graalvmLVMJavaEspresso框架
- Springboot啟動時執行指定程式碼Spring Boot
- Java程式碼寫好後怎麼執行?Java
- java類內部程式碼執行順序Java
- 【28】VsCode如何執行C#程式碼VSCodeC#
- 如何測量程式碼執行時間
- 程式碼執行
- 如何在Spring Boot應用啟動之後立刻執行一段邏輯Spring Boot
- 【MySQL】一、如何快速執行 binlogMySql
- 低程式碼如何“拯救”企業?
- Java 執行緒池之FixedThreadPool(Java程式碼實戰-003)Java執行緒thread
- Jest如何有序地執行測試
- appium ios java 指令碼如何用指令執行,例如 adb 那種方式執行指令碼APPiOSJava指令碼
- [20190510]快速建立執行指令碼.txt指令碼
- 如何在NotePad++中執行PHP程式碼?PHP
- IDEA如何快速地切換git分支程式碼,本地和遠端的IdeaGit
- ERP:如何快速、低過錯率地完結根底資料準備?