0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

MySQL使用jemalloc作为内存管理器时的解决方法

安芯教育科技 来源:极术社区 作者:Martin1983 2022-05-11 09:34 次阅读

本文主要介绍在ARM64 CentOS系统下,MySQL使用jemalloc作为内存管理器时,内存占用问题的分析过程和解决方法。

Jemalloc 简介

Jemalloc是由Jason Evans在FreeBSD项目中引入的内存分配管理器,它的优势在于减少内存碎片和提升高并发场景下内存的分配效率。

Jemalloc中的基本概念和数据结构
  • size_class: 每个 size_class 代表 jemalloc 分配的内存大小,共有 NSIZES(232)个小类(如果用户申请的大小位于两个小类之间,会取较大的,比如申请14字节,位于8和16字节之间,按16字节分配),分为2大类:small_class和large_class

  • Base: 用于分配 jemalloc 元数据内存的结构,通常一个 base 大小为 2mb, 所有 base 组成一个链表。

  • bin: 管理正在使用中的 slab(即用于小内存分配的 extent) 的集合,每个 bin 对应一个 size_class

  • extent: 管理 jemalloc 内存块(即用于用户分配的内存)的结构,每一个内存块大小可以是 N*page_size(N >= 1)。

  • slab: 当 extent 用于分配 small_class 内存时,称其为 slab。一个 extent 可以被用来处理多个同一size_class 的内存申请。

  • extents: 管理 extent 的集合。

  • arena: 用于分配&回收 extent 的结构,每个用户线程会被绑定到一个 arena 上,默认每个逻辑 CPU 会有 4 个 arena 来减少锁的竞争,各个 arena 所管理的内存相互独立。

  • rtree: 全局唯一的存放每个 extent 信息的 Radix Tree

  • cache_bin: 每个线程独有的用于分配小内存的缓存

  • tcache: 每个线程独有的缓存(Thread Cache),大多数内存申请都可以在 tcache 中直接得到,从而避免加锁

  • tsd: Thread Specific Data,每个线程独有,用于存放与这个线程相关的结构

    7d05838c-d0c7-11ec-bce3-dac502259ad0.png

MySQL使用Jemalloc

鉴于jemalloc的诸多优点,计划使用jemalloc作为内存管理器来优化MySQL,下面是测试环境。

测试环境

CPU: ARM64
Memory: 512GB
OS: CentOS Linux release 8.3.2011
Kernel: 4.18.0-193.28.1.el8_2.aarch64
MySQL: 8.0.25
Test Tool: SysBench 1.0.20
Jemalloc: 5.2.1

jemalloc的安装和使用


	# wget https://github.com/jemalloc/jemalloc/archive/refs/tags/5.2.1.tar.gz -O jemalloc-5.2.1.tar.gz # tar xzvf jemalloc-5.2.1.tar.gz # cd jemalloc-5.2.1 # ./autogen.sh //安装到指定目录 # ./configure --prefix=/home/test-user/jemalloc-5.2.1-install //编译并安装 # make; make install //配置环境变量 # export LD_PRELOAD=/home/test-user/jemalloc-5.2.1-install/lib/libjemalloc.so安装好MySQL后,通过如下命令检查jemalloc是否被正常使用(MySQL的安装请参考官方步骤,这里不再赘述)

	# lsof -n |grep jemalloc下图显示MySQL已经正常使用jemalloc 7d60d4d0-d0c7-11ec-bce3-dac502259ad0.png

测试用例

sysbench启动80个线程对MySQL进行读写压测。

异常问题

压测过程中发现内存使用“异常”:MySQL进程占用的物理内存超过了100GB。 7dca680a-d0c7-11ec-bce3-dac502259ad0.png  不使用jemalloc切换回默认的glibc后,内存占用降低到了7GB,和以往的测试结果一致。 7e04ac5e-d0c7-11ec-bce3-dac502259ad0.png  从测试结果看,使用jemalloc作为内存管理器时内存使用量激增,需要进一步分析原因。内存使用量是否合理?是否和架构相关?

问题分析

第一阶段分析

1. 复现“问题”
首先需要确定该“问题”是否在x86架构上也存在,是否和操作系统或内核版本相关。为了快速验证以上疑问,在AWS上分别创建x86实例(m5)和arm64实例(m6g)进行测试, 并没有复现“问题”。这两个实例默认的操作系统是Amazon Linux 2,而本地测试时使用的是CentOS8,在m6g上安装CentOS8重新测试,“问题”复现。测试结果如下: 7e18e4b2-d0c7-11ec-bce3-dac502259ad0.png
2. 对比分析
对比测试环境,分析它们不同点,我们发现该“问题”只有在内核page size是64KB时才会出现。另外,根据前文介绍,jemalloc中extent会基于page size分配内存。而且,深入分析jemalloc代码后还发现有多个数据结构的内存分配都涉及到page size,比如size_class, bin, extents, arena等等。页表在操作系统中作为最基础的内存分配结构,ARM64支持4K、16K、64K不同大小的页表,x86只支持4KB。而本地测试使用的ARM64 CentOS的默认page size就是64KB,所以初步判断该“问题”和page size的配置相关。
3. 解决方法
即然ARM64架构支持多种page size,而page size为4KB时没有出现问题,那么可以修改ARM64 CentOS8的内核默认的page size来解决该"问题"。
修改page size方法
由于内核当前页表大小只支持静态配置,不支持动态修改,所以需要重新编译内核。修改方法如下:
  • https://www.kernel.org/获取需要的内核版本

  • 解压并修改内核配置参数

    
    			# tar xf linux-x.x.x.tar.xz # cd linux-x.x.x # cp /boot/config-xxx .config # make menuconfig
  • 在图形菜单中找到“Kernel Features-> Page size”,选择4KB并保存配置

    7e4f2036-d0c7-11ec-bce3-dac502259ad0.png

  • 编译并安装新的内核

    
    			# make -j # make modules_install # make install
  • 重启进入新的内核,参看page size是否修改成功

    
    			# getconf PAGE_SIZE 4096
4. 验证
修改page size为4KB后重新测试,jemalloc内存使用量和glibc接近。测试结果如下: 7e7bf4c6-d0c7-11ec-bce3-dac502259ad0.png
5. 潜在问题
至此该“问题”似乎可以通过修改page size来解决。但是,如果用户仍然需要使用64KB的页表,该方法将不再适用。实际上,jemalloc本身支持编译参数“--with-lg-page=16”,该参数可以使jemalloc在page size为4KB时复用多个页面来达到使用64KB页面的效果。尝试在4KB page size的系统下加入该编译参数,并没有出现内存使用量激增的现象。这说明除了page size,还有其他因素影响了jemalloc的内存分配,仍然需要进一步分析。

第二阶段分析

1. micro-benchmark
通过以上测试发现该“问题”和MySQL并没有直接关系。为了简化分析和复现过程,单独开发了一个micro-benchmarkhttps://github.com/machuang1983/jemalloc_micro_benchmark该程序用于建立多个线程,每个线程分配一定内存,程序运行过程中实时打印进程的内存使用情况。通过micro-benchmark可以快速复现问题。测试结果显示,每新建一个线程就会消耗1GB左右的内存。测试结果如下: 7e963aa2-d0c7-11ec-bce3-dac502259ad0.png  再次简化测试,直接运行单线程程序,如sleep 100,进程就会占用1GB内存。 7ea64b36-d0c7-11ec-bce3-dac502259ad0.png  由此看见,jemalloc针对一个线程进行内存初始化分配时就会分配1GB内存。需要深入分析jemalloc具体的分配机制。
2. 深入分析jemalloc代码
按前文所述,jemalloc的内存分配涉及到多个数据结构,我们结合gdb单步执行来分析jemalloc代码,同时实时查看内存占用的变化,由此定位到关键代码。调试过程中发现,base会基于默认的hugepage size分配内存,分配之后监控到内存使用量突然增大,具体代码在https://github.com/jemalloc/jemalloc/blob/dev/src/base.c#L46-L497ec45d6a-d0c7-11ec-bce3-dac502259ad0.png  继续搜索hugepage size相关代码,还发现另一处使用它来分配内存,代码在https://github.com/jemalloc/jemalloc/blob/master/src/arena.c#L2052 7efeb80c-d0c7-11ec-bce3-dac502259ad0.png  由此可见除了page size,hugepage size对jemalloc的内存分配也有影响。通常hugepage size比page size大得多,所以hugepage size的影响会更大。
3. hugepage
内存管理采用"分页机制",但是当运行内存需求量较大时,默认page大小的页面会导致较多的TLB miss和缺页中断,从而大大影响应用程序性能。所以,有些场景希望可以使用更大的内存页作为映射单位,因此引入了hugepage。不同架构支持的hugepage size不同,见下表: 7f5f9d02-d0c7-11ec-bce3-dac502259ad0.png
4. 解决方法
ARM64 CentOS在page size=64KB时,默认hugepage size是512MB,jemalloc的base会以512MB来分配内存,而当page size=4KB时,默认hugepage size是2MB。所以回顾前面的测试,修改page size后问题消失的主要原因是默认的hugepage size改变导致的。
默认hugepage size修改方法
  1. 修改启动参数“default_hugepagesz=2M” ARM64支持多种hugepage size,可以使用hugepagesz启动参数进行调整,无需重新编译内核。
  • 内核启动时,输入"e"进入修改启动选项界面,加入参数“default_hugepagesz=2M”,然后输入"ctrl+x"启动内核。
  • Centos: Set default_hugepagesz=2M in /boot/grub2/grubenv file
  • Ubuntu: Set default_hugepagesz=2M to GRUB_CMDLINE_LINUX in /etc/default/grub file, then run “update-grub”
  • 永久修改
  • 临时修改
  • jemalloc编译参数"--with-lg-hugepage=21" jemalloc支持编译参数"--with-lg-hugepage=21",替代系统的默认的hugepage size为2MB。建议使用该方法。
5. 验证
修改默认hugepage size后测试结果(sysbench使用256线程压测)如下: 7f77cd6e-d0c7-11ec-bce3-dac502259ad0.png  测试结果显示,将hugepage size改为2MB以后,jemalloc的内存使用情况和glibc接近。

总结

该"问题"和架构无关,jemalloc作为内存管理器,如果默认hugepage size较大,会导致软件占用较大的内存,jemalloc提供了编译参数"--with-lg-hugepage=21"来降低这个影响。由于ARM64支持更多类型的page size和hugepage size,用以提升软件的性能。所以用户在ARM64系统上使用jemalloc时,需要关注默认的page size和hugepage size,并根据具体需求做出相应的调整。
审核编辑 :李倩

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 管理器
    +关注

    关注

    0

    文章

    242

    浏览量

    18489
  • MySQL
    +关注

    关注

    1

    文章

    802

    浏览量

    26442
  • 线程
    +关注

    关注

    0

    文章

    504

    浏览量

    19651
  • malloc
    +关注

    关注

    0

    文章

    52

    浏览量

    69

原文标题:技术分享 | Arm64 CentOS系统下MySQL使用jemalloc时的问题和解决方法

文章出处:【微信号:Ithingedu,微信公众号:安芯教育科技】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    RAM内存不足的表现及解决方法

    RAM内存不足的表现及解决方法 一、RAM内存不足的表现 系统运行缓慢 当RAM内存不足时,计算机的响应速度会明显下降,打开程序或文件需要更长的时间。 频繁的页面交换(Page Swa
    的头像 发表于 11-11 09:53 318次阅读

    如何检测电脑的RAM内存

    和评估电脑的RAM内存呢? 1. 通过操作系统检测RAM 1.1 Windows系统 在Windows操作系统中,有几种方法可以查看RAM信息: 任务管理器 :按 Ctrl + Shift + Esc 打开任务
    的头像 发表于 11-11 09:51 204次阅读

    bq40z50EVM锂离子电池包管理器评估模块

    电子发烧友网站提供《bq40z50EVM锂离子电池包管理器评估模块.pdf》资料免费下载
    发表于 11-07 09:42 0次下载
    bq40z50EVM锂离子电池包<b class='flag-5'>管理器</b>评估模块

    TLV320AIC31的HPLOUT输出到音频管理器,音频管理器输出接到耳机,声音几乎听不到怎么处理?

    TLV320AIC31的HPLOUT后面接到音频管理器的输入,对我这边要求是,匹配阻抗600欧姆时,输出电压最大有效值800mv,请问TLV320AIC31的HPLOUT满足这样的输出要求吗,还是说必须
    发表于 10-12 07:02

    负载管理器的主要功能

    负载管理器(Load Manager)是计算机系统中的一个关键组件,它负责分配和管理计算资源,以确保系统运行的效率和稳定性。负载管理器的主要功能包括任务调度、资源分配、性能监控、故障恢复等。以下
    的头像 发表于 10-10 11:26 285次阅读

    打开labview时很慢,在任务管理器里面看到,内存能有1000多M,重装也没用,各位大佬这是什么问题引起的,怎么解决

    打开labview时很慢,在任务管理器里面看到,内存能有1000多M,重装也没用,各位大佬这是什么问题引起的,怎么解决
    发表于 09-14 09:24

    如何判断反射内存卡是否安装成功

    要判断反射内存卡是否安装成功,可以通过以下几种方法:在操作系统中查看设备管理器:-Windows系统:按下`Win+X`组合键,选择“设备管理器”。2.在设备
    的头像 发表于 09-05 14:39 229次阅读
    如何判断反射<b class='flag-5'>内存</b>卡是否安装成功

    鸿蒙OpenHarmony:【常见编译问题和解决方法

    常见编译问题和解决方法
    的头像 发表于 05-11 16:09 1970次阅读

    家用路由常见问题及解决方法

    家用路由已成为我们家庭中不可或缺的一部分。然而,由于各种原因,家用路由可能会遇到各种各样的问题。本文将介绍一些常见的家用路由问题及相应的解决方法,以帮助读者更好地维护和
    的头像 发表于 04-18 17:42 914次阅读

    Windows 11 22H2新版任务管理器新增启用隐藏功能

    关于如何隐藏调用旧版任务管理器,网友 @thebookisclosed 分享了详细步骤。他指出,在现有 Windows 11 环境中,即使按 Ctrl+Shift+Esc 组合键也难以调出老版本的任务管理器,需通过特定路径“C:\Windows\SysWOW64\Task
    的头像 发表于 03-27 15:08 456次阅读

    MySQL密码忘记了怎么办?MySQL密码快速重置方法步骤命令示例!

    MySQL密码忘记了怎么办?MySQL密码快速重置方法步骤命令示例! MySQL是一种常用的关系型数据库管理系统,如果你忘记了
    的头像 发表于 01-12 16:06 723次阅读

    导致MySQL索引失效的情况以及相应的解决方法

    导致MySQL索引失效的情况以及相应的解决方法  MySQL索引的目的是提高查询效率,但有些情况下索引可能会失效,导致查询变慢或效果不如预期。下面将详细介绍导致MySQL索引失效的情况
    的头像 发表于 12-28 10:01 731次阅读

    mysql密码忘了怎么重置

    mysql密码忘了怎么重置  MySQL是一种开源的关系型数据库管理系统,密码用于保护数据库的安全性和保密性。如果你忘记了MySQL的密码,可以通过以下几种
    的头像 发表于 12-27 16:51 6339次阅读

    SNMP配置及网络管理系统无法接收告警(Trap)的解决方法

    本文将详细介绍如何配置SNMP,并探讨网络管理系统(NMS)无法接收告警(Trap)的原因及解决方法。SNMP(简单网络管理协议)是一种用于管理和监控网络设备的协议,而NMS则是用于集
    的头像 发表于 12-27 13:58 1730次阅读

    php的mysql无法启动

    MySQL是一种常用的关系型数据库管理系统,而PHP是一种广泛应用于服务端的脚本语言。在使用PHP开发网站或应用时,经常会碰到MySQL无法启动的问题。本文将详细介绍解决
    的头像 发表于 12-04 15:59 1443次阅读