1. 程式人生 > >實戰JAVA虛擬機器:在TLAB上分配物件

實戰JAVA虛擬機器:在TLAB上分配物件

TLAB全稱是Thread Local Allocation Buffer 即執行緒本地分配快取,從名字上看是一個執行緒專用的記憶體分配區域。

為什麼需要TLAB這個區域呢?這是為了加速物件分配而生的。由於物件一般會分配在堆上,而堆是全域性共享的。所以存在多個執行緒在堆上申請空間。因此,每一次物件分配都必須要進行同步(虛擬機器採用CAS配上失敗重試的方式保證更新操作的原子性),而在競爭激烈的場合分配的效率又會進一步下降。考慮到物件分配幾乎是Java最常用的操作,因此Java虛擬機器就使用了TLAB這種執行緒專屬的區間來避免多執行緒衝突,提高了物件分配效率。TLAB本身佔用了eden區的空間。在TLAB啟用的情況下,虛擬機器會為每一個Java執行緒分配一塊TLAB空間。

由於TLAB空間一般不會很大,因此大物件無法在TLAB上進行分配,總是會直接分配在堆上。TLAB空間由於比較小,因此很容易裝滿。比如,一個100K的空間,已經使用了80KB,當需要再分配一個30KB的物件時,肯定就無能為力了。這時虛擬機器會有兩種選擇,第一,廢棄當前TLAB,這樣就會浪費20KB空間;第二,將這30KB的物件直接分配在堆上,保留當前的TLAB,這樣可以希望將來有小於20KB的物件分配請求可以直接使用這塊空間。實際上虛擬機器內部會維護一個叫作refill_waste的值,當請求物件大於refill_waste時,會選擇在堆中分配,若小於該值,則會廢棄當前TLAB,新建TLAB來分配物件。這個閾值可以使用TLABRefillWasteFraction來調整,它表示TLAB中允許產生這種浪費的比例。預設值為64,即表示使用約為1/64的TLAB空間作為refill_waste。

預設情況下,TLAB和refill_waste都會在執行時不斷調整的,使系統的執行狀態達到最優。如果想要禁用自動調整TLAB的大小,可以使用-XX:-ResizeTLAB禁用ResizeTLAB,並使用-XX:TLABSize手工指定一個TLAB的大小。

如圖展示了簡要的物件分配流程。首先,如果執行棧上分配,系統會先進行棧上分配,沒有開啟棧上分配或者不符合條件則會進行TLAB分配,如果TLAB分配不成功,再嘗試在堆上分配,如果滿足了進入老年代的條件(PretenureSizeThreshold等引數),就在老年代分配,否則就在eden區分配物件,當然有必要,可能會進行一次新生代GC。

個人微信公眾號:
這裡寫圖片描述