Presto内存管理源码分析
生活随笔
收集整理的這篇文章主要介紹了
Presto内存管理源码分析
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1. 內存池初始化
初始化代碼在LocalMemoryManager中,啟動時將內存分為3個內存池,分別是:
- RESERVED_POOL:預留內存池,用于執行最耗費內存資源的查詢。
- GENERAL_POOL:普通內存池,用于執行除最耗費內存查詢以外的查詢。
- SYSTEM_POOL:系統內存池,預留的用于Presto內部數據結構和臨時的分配需求使用的內存。
2. 定時調整內存池分配策略
首先看SqlQueryManager的代碼
queryManagementExecutor.scheduleWithFixedDelay(() -> {...enforceMemoryLimits();... }, 1, 1, TimeUnit.SECONDS); //每隔1S觸發一次其調用的是ClusterMemoryManager的process方法,其中有一行:
updateNodes(updateAssignments(queries));我們看updateAssignments方法,其作用是找出最耗費內存的查詢,并放入RESERVED_POOL:
if (reservedPool.getAssignedQueries() == 0 && generalPool.getBlockedNodes() > 0) { //要求reservedPool當前沒有分配查詢,并且generalPool中有阻塞的節點QueryExecution biggestQuery = null;long maxMemory = -1;for (QueryExecution queryExecution : queries) {if (resourceOvercommit(queryExecution.getSession())) {// 不要提升那些請求資源過量使用的查詢到reserved pool,因為他們的內存使用是沒有限制的。continue;}long bytesUsed = queryExecution.getTotalMemoryReservation();if (bytesUsed > maxMemory) {biggestQuery = queryExecution;maxMemory = bytesUsed;}}if (biggestQuery != null) {biggestQuery.setMemoryPool(new VersionedMemoryPoolId(RESERVED_POOL, version));} }再看外層的updateNodes方法,可以發現RESERVED POOL的這種分配策略會應用到每個節點。也就是說這個查詢在每個節點都會獨占RESERVED POOL的空間。
// Schedule refresh for (RemoteNodeMemory node : nodes.values()) {node.asyncRefresh(assignments); }3. 配置優化
以下是調整前的Presto的配置
query.max-memory=14GB query.max-memory-per-node=7GB resources.reserved-system-memory=2GB -Xmx10G計算可得:
- 節點總內存:10GB
- RESERVED_POOL(預留內存池):7GB
- GENERAL_POOL(普通內存池):1GB
- SYSTEM_POOL(系統內存池):2GB
分析:
- 實際執行查詢發現SYSTEM_POOL最大使用量大概在1.3GB,基本符合要求。
- 當只提交一個查詢時,該查詢會進入GENERAL POOL,并出現了可用量為負數的情況(即可用量已無法完成查詢),而此時RESERVED POOL的可用量卻為7GB,一點都沒使用。
- 可以得出目前RESERVED_POOL設置的不太合理,可改為2GB。
保持總內存不變進行修改,修改后配置:
query.max-memory=14GB query.max-memory-per-node=2GB resources.reserved-system-memory=2GB -Xmx10G經測試,該配置可以較好的利用資源。
總結
以上是生活随笔為你收集整理的Presto内存管理源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据仓库与联机分析处理笔记
- 下一篇: 在Java语言里 ==和equals的区