之前介紹過presto記憶體管理和分配策略,但是那個是0.192版本,詳細見:presto記憶體管理原理和調優 ,0.201之後記憶體管理作了新的修改,所以重新簡單分析下,然後給出乙個配置模板,希望對使用presto的同學有幫助。
presto裡面記憶體只有2種記憶體,一種是user memory,另一種是system memory。system memory用於input/output/exchange buffers等,user memory 用於hash join、agg這些。
0.201之前有3種記憶體pool,分別是general_pool、reserved_pool及system_pool。但是0.201之後,預設system_pool是不開啟的,以下引數控制,預設值為false
deprecated.legacy-system-pool-enabled
那system_pool不使用了,這塊記憶體怎麼控制呢,去**裡確認了下:
sqltaskmanager#createquerycontext
private querycontext createquerycontext(
queryid queryid,
localmemorymanager localmemorymanager,
nodememoryconfig nodememoryconfig,
localspillmanager localspillmanager,
gcmonitor gcmonitor,
datasize maxqueryusermemorypernode,
datasize maxquerytotalmemorypernode,
datasize maxqueryspillpernode)
return new defaultquerycontext(
queryid,
maxqueryusermemorypernode,
maxquerytotalmemorypernode,
localmemorymanager.getgeneralpool(),
gcmonitor,
tasknotificationexecutor,
driveryieldexecutor,
maxqueryspillpernode,
localspillmanager.getspillspacetracker());
}
}
可以看到systempool.get()被替換為了localmemorymanager.getgeneralpool(),所以general_pool扮演了之前general_pool及system_pool的作用,提供user memory和system memory。
說完system_pool,再說下reserved_pool,reserved_pool作用就是當general_pool滿的時候,將最占用記憶體的sql分配到這塊記憶體上來,但是實際使用時,這塊記憶體很少會被使用,原因是, 一般使用presto的業務是用來sql提速的,不會使用spill disk功能,第二為了服務的穩定性,會限制最大記憶體和kill記憶體策略,所以會出現查詢沒有被分配到reserved_pool之前, sql將會被系統kill掉。第三是大查詢一般會用spark/hive替代,所以這塊reserved_pool就會浪費掉了,如下圖所示:
目前有9個sql正在查詢,都在使用general_pool,reserved_pool將會浪費掉。所以對於絕大部分presto使用者,禁止掉reserved_pool是正確的選擇。
memory.heap-headroom-per-node
這個記憶體主要是第三方庫的記憶體分配,無法被統計跟蹤,預設值是xmx*0.3。
所以,presto記憶體分配只需要考慮general_pool及heap-headroom-per-node。
既然presto是乙個純記憶體olap引擎,那肯定不能讓查詢占用的記憶體無限大,需要引數控制sql占用的最大記憶體,presto記憶體管理包括了單機和集群粒度的記憶體,分別是:
而集群query.max-memory由query.initial-hash-partitions控制,預設值為8,那query.max-memroy 一般稍小於query.max-memory-per-node*8即可(考慮到資料傾斜)。
根據**和上面分析知道:
reserved_pool = query.max-total-memory-per-node
所以新的 general_pool = totalmemory - reservedpool - memory.heap-headroom-per-node
禁止掉reserved_pool時:
general_pool= totalmemory - memory.heap-headroom-per-node
綜上,presto合適的記憶體分配配置為如下,假如-xmx80g,worker數大於8臺:
query.max-memory=120gb # 預設為20gb,query.max-memory-per-node * 8 * 0.8 ,傾斜按照0.8算即可
query.max-memory-per-node=20gb # 預設值0.1 * xmx,一般線上按照0.25*xmx算,這個最好結合自己併發,如果併發大,大查詢多,值最好小一點,穩定性考慮
query.max-total-memory-per-node=32gb # 預設值0.3*xmx,一般設定為0.4*xmx
experimental.reserved-pool-enabled=false # 不使用reserved_pool
memory.heap-headroom-per-node=16gb # 預設0.3*xmx,一般使用的是0.2*xmx
query.low-memory-killer.policy=total-reservation-on-blocked-nodes # kill策略,乾掉blocked的最大查詢,general_pool滿了,防止oom
比如上面分配後,general_pool為80gb - 16gb = 64gb,如下圖所示,reserved_pool不再存在。query.max-total-memory預設值為2*query.max-memory,這個引數可以保持預設值即可。
記憶體管理相關函式
記憶體分配及釋放相關函式 void calloc int num,int size 在記憶體中動態地分配 num 個長度為 size 的連續空間,並將每乙個位元組 共num size 個 都初始化為 0。void malloc int num 在堆區分配一塊指定大小的記憶體空間,用來存放資料。這塊記...
記憶體管理相關 記憶體布局 記憶體管理方案
ios系統下的記憶體布局 最上面是核心區,最下面是保留區,中間是給程式載入的空間。從高位址到低位址依次為核心區 棧 堆 靜態全域性區 未初始化區域.bss和已初始化區域.data 區 保留區 程式被載入到記憶體分成三段未初始化資料 bss 已初始化資料 data 和 段 text 段顧名思義存放 已...
QT 相關類記憶體管理
qt記憶體自動釋放兩個前提條件 1 必須是qobject的派生類 2 必須指定了qt類parent物件,則,qt 中 父類被刪除的時候會自動銷毀子類。注意 qt的析構順序先入先出,因此在指定父類時,需要如果建立在棧上 例項化產生,棧的特性 先入後出,先出 需要父類在前例項化,或是堆上 new實現 如...