小師妹學JVM之:JDK14中JVM的性能優化

目錄

  • 簡介
  • String壓縮
  • 分層編譯(Tiered Compilation)
  • Code Cache分層
  • 新的JIT編譯器Graal
  • 前置編譯
  • 壓縮對象指針
  • Zero-Based 壓縮指針
  • Escape analysis逃逸分析

簡介

上一篇文章我們講到了JVM為了提升解釋的性能,引入了JIT編譯器,今天我們再來從整體的角度,帶小師妹看看JDK14中的JVM有哪些優化的方面,並且能夠從中間得到那些啟發。

更多精彩內容且看:

  • 區塊鏈從入門到放棄系列教程-涵蓋密碼學,超級賬本,以太坊,Libra,比特幣等持續更新
  • Spring Boot 2.X系列教程:七天從無到有掌握Spring Boot-持續更新
  • Spring 5.X系列教程:滿足你對Spring5的一切想象-持續更新
  • java程序員從小工到專家成神之路(2020版)-持續更新中,附詳細文章教程

String壓縮

小師妹:F師兄,上次你給我講的JIT真的是受益匪淺,原來JVM中還有這麼多不為人知的小故事。不知道除了JIT之外,JVM還有沒有其他的性能提升的姿勢呢?

姿勢當然有很多種,先講一下之前提到過的,在JDK9中引入的字符串壓縮。

在JDK9之前,String的底層存儲結構是char[],一個char需要佔用兩個字節的存儲單位。

因為大部分的String都是以Latin-1字符編碼來表示的,只需要一個字節存儲就夠了,兩個字節完全是浪費。

於是在JDK9之後,字符串的底層存儲變成了byte[]。

目前String支持兩種編碼格式LATIN1和UTF16。

LATIN1需要用一個字節來存儲。而UTF16需要使用2個字節或者4個字節來存儲。

在JDK9中,字符串壓縮是默認開啟的。你可以使用

 -XX:-CompactStrings

來控制它。

分層編譯(Tiered Compilation)

為了提升JIT的編譯效率,並且滿足不同層次的編譯需求,引入了分層編譯的概念。

大概來說分層編譯可以分為三層:

  1. 第一層就是禁用C1和C2編譯器,這個時候沒有JIT進行。
  2. 第二層就是只開啟C1編譯器,因為C1編譯器只會進行一些簡單的JIT優化,所以這個可以應對常規情況。
  3. 第三層就是同時開啟C1和C2編譯器。

在JDK7中,你可以使用下面的命令來開啟分層編譯:

-XX:+TieredCompilation

而在JDK8之後,恭喜你,分層編譯已經是默認的選項了,不用再手動開啟。

Code Cache分層

Code Cache就是用來存儲編譯過的機器碼的內存空間。也就說JIT編譯產生的機器碼,都是存放在Code Cache中的。

Code Cache是以單個heap形式組織起來的連續的內存空間。

如果只是用一個code heap,或多或少的就會引起性能問題。為了提升code cache的利用效率,JVM引入了Code Cache分層技術。

分層技術是什麼意思呢?

就是把不同類型的機器碼分門別類的放好,優點嘛就是方便JVM掃描查找,減少了緩存的碎片,從而提升了效率。

下面是Code Cache的三種分層:

新的JIT編譯器Graal

之前的文章我們介紹JIT編譯器,講的是JIT編譯器是用C/C++來編寫的。

而新版的Graal JIT編譯器則是用java來編寫的。對的,你沒看錯,使用java編寫的JIT編譯器。

有沒有一種雞生蛋,蛋生雞的感覺?不過,這都不重要,重要的是Graal真的可以提升JIT的編譯性能。

Graal是和JDK一起發行的,作為一個內部的模塊:jdk.internal.vm.compiler。

Graal和JVM是通過JVMCI(JVM Compiler Interface)來進行通信的。其中JVMCI也是一個內部的模塊:jdk.internal.vm.ci。

注意,Graal只在Linux-64版的JVM中支持,你需要使用 -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler 來開啟Graal特性。

前置編譯

我們知道在JIT中,通常為了找到熱點代碼,JVM是需要等待代碼執行一定的時間之後,才開始進行本地代碼的編譯。這樣做的缺點就是需要比較長的時間。

同樣的,如果是重複的代碼,沒有被編譯成為機器碼,那麼對性能就會有影響。

而AOT(Ahead-of-time)就厲害了,看名字就知道是提前編譯的意思,根本就不需要等待,而是在JVM啟動之前就開始編譯了。

AOT提供了一個java tool,名字叫做jaotc。显示jaotc的命令格式:

jaotc <options> <list of classes or jar files>
jaotc <options> <--module name>

比如,我們可以這樣提前編譯AOT庫,以供在後面的JVM中使用:

jaotc --output libHelloWorld.so HelloWorld.class
jaotc --output libjava.base.so --module java.base

上面代碼提前編譯了HelloWorld和它的依賴module java.base。

然後我們可以在啟動HelloWorld的時候,指定對應的lib:

java -XX:AOTLibrary=./libHelloWorld.so,./libjava.base.so HelloWorld

這樣在JVM啟動的時候,就回去找相應的AOTLibrary。

注意,AOT是一個 Linux-x64上面的體驗功能。

壓縮對象指針

對象指針用來指向一個對象,表示對該對象的引用。通常來說在64位機子上面,一個指針佔用64位,也就是8個字節。而在32位機子上面,一個指針佔用32位,也就是4個字節。

實時上,在應用程序中,這種對象的指針是非常非常多的,從而導致如果同樣一個程序,在32位機子上面運行和在64位機子上面運行佔用的內存是完全不同的。64位機子內存使用可能是32位機子的1.5倍。

而壓縮對象指針,就是指把64位的指針壓縮到32位。

怎麼壓縮呢?64位機子的對象地址仍然是64位的。壓縮過的32位存的只是相對於heap base address的位移。

我們使用64位的heap base地址+ 32位的地址位移量,就得到了實際的64位heap地址。

對象指針壓縮在Java SE 6u23 默認開啟。在此之前,可以使用-XX:+UseCompressedOops來開啟。

Zero-Based 壓縮指針

剛剛講到了壓縮過的32位地址是基於64位的heap base地址的。而在Zero-Based 壓縮指針中,64位的heap base地址是重新分配的虛擬地址0。這樣就可以不用存儲64位的heap base地址了。

Escape analysis逃逸分析

最後,要講的是逃逸分析。什麼叫逃逸分析呢?簡單點講就是分析這個線程中的對象,有沒有可能會被其他對象或者線程所訪問,如果有的話,那麼這個對象應該在Heap中分配,這樣才能讓對其他的對象可見。

如果沒有其他的對象訪問,那麼完全可以在stack中分配這個對象,棧上分配肯定比堆上分配要快,因為不用考慮同步的問題。

我們舉個例子:

  public static void main(String[] args) {
    example();
  }
  public static void example() {
    Foo foo = new Foo(); //alloc
    Bar bar = new Bar(); //alloc
    bar.setFoo(foo);
  }
}

class Foo {}

class Bar {
  private Foo foo;
  public void setFoo(Foo foo) {
    this.foo = foo;
  }
}

上面的例子中,setFoo引用了foo對象,如果bar對象是在heap中分配的話,那麼引用的foo對象就逃逸了,也需要被分配在heap空間中。

但是因為bar和foo對象都只是在example方法中調用的,所以,JVM可以分析出來沒有其他的對象需要引用他們,那麼直接在example的方法棧中分配這兩個對象即可。

逃逸分析還有一個作用就是lock coarsening。

為了在多線程環境中保證資源的有序訪問,JVM引入了鎖的概念,雖然鎖可以保證多線程的有序執行,但是如果實在單線程環境中呢?是不是還需要一直使用鎖呢?

比如下面的例子:

public String getNames() {
     Vector<String> v = new Vector<>();
     v.add("Me");
     v.add("You");
     v.add("Her");
     return v.toString();
}

Vector是一個同步對象,如果是在單線程環境中,這個同步鎖是沒有意義的,因此在JDK6之後,鎖只在被需要的時候才會使用。

這樣就能提升程序的執行效率。

本文作者:flydean程序那些事

本文鏈接:http://www.flydean.com/jvm-performance-enhancements/

本文來源:flydean的博客

歡迎關注我的公眾號:程序那些事,更多精彩等着您!

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準

聚甘新