Jit

Jit編譯:just in time 編譯. Java代碼只有在執行一段時間之後纔會進行jit編譯。異步

Hotspot會編譯優化那些熱點代碼,以求最大的性能收益。性能

Jit編譯的好處:優化

    1. 執行一段時間後,能夠統計出哪些代碼的調用頻次高。線程

    2. 執行一段時間後,編譯器能夠得到代碼的一些性能信息,來加大編譯優化的力度。因此,如今的jit編譯優化甚至可能比C語言的編譯優化作的還要效果好。日誌

 

jit編譯器有倆種:C1(client),和C2(Server) 倆種編譯器。code

   C1:編譯的時機要比C2快,編譯的代碼要比C2多。好處了能夠在程序啓動剛開始就能得到比較好的性能。應用啓動時間快。server

   C2:編譯的時機要比C1晚,由於它但願能夠得到更多的統計信息,進行優化程度更高的優化處理。應用啓動時間慢。隊列

   分層編譯:程序在剛啓動的時候進行C1編譯,隨着代碼執行的時間增長,再慢慢進行C2編譯。內存

 

應用運行的時間短就採用C1,不然使用C2。通常來講,用分層編譯老是沒錯的。資源

 

Jit編譯後的字節碼會保存在code-cache中,而code-cache的大小是有限的。使用C1或者分層編譯所編譯的代碼較多,比較容易填滿codecache,而C2編譯的代碼量不會那麼多。能夠經過-XX:ReservedCodeCacheSize=N 來設置code-cache的最大值。須要注意的是,任何內存區均可能進行內存保留,因此把最大值設大,可能會致使佔用過多的內存。也就是由於內存的消耗,因此,咱們須要考慮機器資源來權衡jit編譯的程度,來最大化應用的性能。

 

JVM有倆個參數:方法調用計數器和循環回邊計數器。

標準編譯:當方法調用計數器和循環回邊計數器記錄的總次數超過必定的閾值,就對一個方法進行jit編譯。

棧上替換:若是方法計數器的值沒有達到閾值,可是循環回邊計數器達到的必定的值,會對這個循環進行編譯,而不會對整個方法進行編譯,並在方法棧上進行替換。

C1和C2在編譯時機上的不一樣主要是因爲這倆個計數器的閾值是不一樣的。另外,計數器的值還會週期性的減小,因此它表示的是最新的調用熱度。jit編譯的閾值是能夠調節的,可是要考慮到調整完後對code-cache帶來的消耗。

 

對jit編譯狀況進行統計的方法有:

1. 開啓 -XX:+PrintCompilation 

2. Jstat -compiler pid

   jstat -printcompilation 

 

 

編譯線程:編譯的操做是異步的,會有編譯線程在後臺對達到要求的代碼進行編譯。線程分爲client線程和server線程,分別用於C1,C2編譯器。分層編譯倆種線程都有。編譯線程的量是可調節的,可是這一般影響的是應用在熱身期的性能。若是過了熱身期,這些編譯線程就不會在佔用cpu了。

 

內聯:內聯帶來的性能提高是巨大的,一方面是內聯自己帶來的方法調用的減小。另外一個是否重要的方面是,內聯後的代碼,又能夠促進不少其餘優化。內聯的關閉-XX:-Inline (默認是開的)

常規的內聯:當方法很小時會進行內聯。小於35個字節或-XX:MaxInlineSize=N 所設的值。

頻繁調用帶來的內聯:當調用很頻繁時,若是小於325個字節或者-XX:MaxFreqInlineSize=N 所設定的值。

 

逃逸分析(-XX:+DoEscapeAnalysis,默認爲 true) ,編譯器會作一些很是複雜和激進的優化。好比把一些沒有用到的變量的計算省略掉。

 

逆優化:指編譯器對一些編譯進行撤回。有兩種逆優化的情形:代碼狀態分別爲「made not entrant」(代碼被丟棄)和「made zombie」(產生殭屍代碼) 

 

「made not entrant」(代碼被丟棄)的發生有倆種狀況:

   1. 若是一個方法內部的一個邏輯分支一直被調用,而後進行了jit編譯,若是這時出現了另外一個邏輯分支的調用,就會致使原來的編譯代碼失效,而後被丟棄。在編譯的詳情日誌裏也會出現made not entrant,而後會出現made zombie 

   2. 在分層編譯中,C1編譯的代碼,接着被C2編譯後,以前的jit編譯的代碼就會被丟棄。

 

「made zombie」(產生殭屍代碼) :指上面被丟棄的代碼被GC回收了。

 

分層編譯級別:

  • 0:解釋代碼 
  • 1:簡單 C1 編譯代碼 
  • 2:受限的 C1 編譯代碼 
  • 3:徹底 C1 編譯代碼 
  • 4:C2 編譯代碼 

C1和C2都有本身的編譯隊列,存儲達到閾值的須要編譯的代碼。若是C2的隊列滿了,則這段代碼會進行2,而後進行C1編譯。等C2隊列空閒後再進行C2編譯。一樣,若是C1編譯隊列滿了,也會進行相似的操做。

相關文章
相關標籤/搜索