Presto内存管理源码分析
1. 内存池初始化
初始化代码在LocalMemoryManager中,启动时将内存分为3个内存池,分别是:
- RESERVED_POOL:预留内存池,用于执行最耗费内存资源的查询。
- GENERAL_POOL:普通内存池,用于执行除最耗费内存查询以外的查询。
- SYSTEM_POOL:系统内存池,预留的用于Presto内部数据结构和临时的分配需求使用的内存。
long maxHeap = Runtime.getRuntime().maxMemory();
//堆内存最大值,由Xmx指定
maxMemory = new DataSize(maxHeap - systemMemoryConfig.getReservedSystemMemory().toBytes(), BYTE);
//扣除系统内存池的剩余最大内存
builder.put(RESERVED_POOL, new MemoryPool(RESERVED_POOL, config.getMaxQueryMemoryPerNode()));
//RESERVED_POOL的大小由MaxQueryMemoryPerNode指定
DataSize generalPoolSize = new DataSize(Math.max(0, maxMemory.toBytes() - config.getMaxQueryMemoryPerNode().toBytes()), BYTE);
builder.put(GENERAL_POOL, new MemoryPool(GENERAL_POOL, generalPoolSize));
//扣除SYSTEM_POOL,再扣除RESERVED_POOL,剩余内存作为GENERAL_POOL
builder.put(SYSTEM_POOL, new MemoryPool(SYSTEM_POOL, systemMemoryConfig.getReservedSystemMemory()));
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内存管理源码分析相关推荐
- 分享一篇glibc 2.30内存管理源码分析
分享一篇glibc 2.30内存管理源码分析,出于时间关系文章中可能存在问题(如纰漏.或者解释不顺,后续我会持续更新修正),还请大家海涵,大家互相探讨,也多多希望大家指出文章中问题,我及时斧正.本文只 ...
- Linux内核手帐之内存管理源码分析(一)
最近再阅读LINUX内核内存部分源码,边读便记录,就当知识积累了.(这里分析源码版本是linux 5.7-rc4) 在linux源码中内存无论是以UMA还是NUMA的计算机类型,都是以[NODE-& ...
- 内存管理源码分析1-ARMV8-AARCH64 MMU 及 linux页表映射过程
MMU的作用,主要是完成地址的翻译,无论是main-memory地址(DDR地址),还是IO地址(设备device地址),在开启了MMU的系统中,CPU发起的指令读取.数据读写都是虚拟地址,在ARM ...
- 华为liteos内存管理源码以及架构分析
文章目录 华为liteos内存管理源码以及架构分析 牵扯到的主要数据结构 华为liteos内存管理源码以及架构分析 本文主要从源码层面讲解华为针对物联网的一个小型操作系统liteos的内存管理方式: ...
- linux源码文件名,Linux中文件名解析处理源码分析
Linux中文件名解析处理源码分析 前言 Linux中对一个文件进行操作的时候,一件很重要的事情是对文件名进行解析处理,并且找到对应文件的inode对象,然后创建表示文件的file对象.在此,对文件名 ...
- 动态代理原理源码分析
看了这篇文章非常不错转载:https://www.jianshu.com/p/4e14dd223897 Java设计模式(14)----------动态代理原理源码分析 上篇文章<Java设计模 ...
- Linux内核 eBPF基础:kprobe原理源码分析:源码分析
Linux内核 eBPF基础 kprobe原理源码分析:源码分析 荣涛 2021年5月11日 在 <Linux内核 eBPF基础:kprobe原理源码分析:基本介绍与使用>中已经介绍了kp ...
- Linux内核 eBPF基础:kprobe原理源码分析:基本介绍与使用示例
Linux内核 eBPF基础 kprobe原理源码分析:基本介绍与使用示例 荣涛 2021年5月11日 kprobe调试技术是为了便于跟踪内核函数执行状态所设计的一种轻量级内核调试技术. 利用kpro ...
- REST framework 权限管理源码分析
REST framework 权限管理源码分析 同认证一样,dispatch()作为入口,从self.initial(request, *args, **kwargs)进入initial() def ...
最新文章
- 在结构化场景中基于单目的物体与平面SLAM方案
- DFS深度优先搜索算法/BFS广度优先搜索算法(c/c++)
- 化工设备与反应器 第三章 直梁的弯曲
- (转)三大博弈定义+结论
- 12 计算机组成原理第七章 输入/输出系统 中断系统
- 谈谈技术原则,技术学习方法,代码阅读及其他的(引用)
- python怎么把数据存在本地_将Python中的数据存储到系统本地的简单方法
- facebook react.js
- java导出excel 自定义表头
- android源代码中repo升级后出现的问题
- Html调用手机打电话功能
- 关于textarea打印问题
- python3精简笔记(三)——高级特性
- 汽车维修店如何挖掘潜在客户资源
- 怎么添加扫描仪到计算机快捷键,Win7系统扫描仪添加方法
- 卷积网络中的通道(channel)和特征图(feature map)
- 输入年月日,获得下个月的同一天,如果该天不存在,则顺延一天
- 番外篇--C++中的代码重用
- CSS垂直及水平居中小技巧
- mysql截取字符串函数