[转帖]ARM64 CentOS系统下MySQL使用jemalloc时的问题和解决方法

arm64,centos,系统,mysql,使用,jemalloc,问题,解决,方法 · 浏览次数 : 0

小编点评

## 问题分析 1. 由于jemalloc针对不同架构支持的hugepage size,用户需要关注默认的page size和hugepage size,并根据具体需求做出相应的调整。 2. 针对page size=4KB时,默认hugepage size是2MB,而页面大小为64KB时,默认hugepage size是512MB,用户需要选择合适的page size和hugepage size。 3. 由于jemalloc采用“分页机制”,默认page size可能导致TLB miss和缺页中断,影响应用程序性能。 4. 用户可以根据需要调整jemalloc的编译参数,降低软件占用内存。 5. 验证修改默认hugepage size后测试结果显示,将hugepage size改为2MB以后,jemalloc的内存使用情况和glibc接近。 ## 解决方案 1. 用户可以设置jemalloc的编译参数,降低软件占用内存。 2. 用户可以选择合适的page size和hugepage size,以提升软件的性能。 3. 用户可以根据具体需求调整jemalloc的编译参数,降低软件占用内存。 4. 用户可以根据需要调整jemalloc的编译参数,降低软件占用内存。 5. 用户可以验证修改默认hugepage size后测试结果,以确保软件正常运行。

正文

https://aijishu.com/a/1060000000321521

 

 

本文主要介绍在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,每个线程独有,用于存放与这个线程相关的结构
     title=

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
 title=

测试用例

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

异常问题

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

问题分析

第一阶段分析

1. 复现“问题”

首先需要确定该“问题”是否在x86架构上也存在,是否和操作系统或内核版本相关。

为了快速验证以上疑问,在AWS上分别创建x86实例(m5)和arm64实例(m6g)进行测试, 并没有复现“问题”。这两个实例默认的操作系统是Amazon Linux 2,而本地测试时使用的是CentOS8,在m6g上安装CentOS8重新测试,“问题”复现。测试结果如下:
 title=

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并保存配置
     title=

  • 编译并安装新的内核

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

    # getconf PAGE_SIZE
    4096
4. 验证

修改page size为4KB后重新测试,jemalloc内存使用量和glibc接近。测试结果如下:
 title=

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-benchmark https://github.com/machuang1983/jemalloc_micro_benchmark

该程序用于建立多个线程,每个线程分配一定内存,程序运行过程中实时打印进程的内存使用情况。

通过micro-benchmark可以快速复现问题。测试结果显示,每新建一个线程就会消耗1GB左右的内存。测试结果如下:
image.png

再次简化测试,直接运行单线程程序,如sleep 100,进程就会占用1GB内存。
 title=
由此看见,jemalloc针对一个线程进行内存初始化分配时就会分配1GB内存。需要深入分析jemalloc具体的分配机制。

2. 深入分析jemalloc代码

按前文所述,jemalloc的内存分配涉及到多个数据结构,我们结合gdb单步执行来分析jemalloc代码,同时实时查看内存占用的变化,由此定位到关键代码。

调试过程中发现,base会基于默认的hugepage size分配内存,分配之后监控到内存使用量突然增大,具体代码在 https://github.com/jemalloc/jemalloc/blob/dev/src/base.c#L46-L49
 title=
继续搜索hugepage size相关代码,还发现另一处使用它来分配内存,代码在https://github.com/jemalloc/jemalloc/blob/master/src/arena.c#L2052
 title=

由此可见除了page size,hugepage size对jemalloc的内存分配也有影响。通常hugepage size比page size大得多,所以hugepage size的影响会更大。

3. hugepage

内存管理采用"分页机制",但是当运行内存需求量较大时,默认page大小的页面会导致较多的TLB miss和缺页中断,从而大大影响应用程序性能。所以,有些场景希望可以使用更大的内存页作为映射单位,因此引入了hugepage。

不同架构支持的hugepage size不同,见下表:
 title=

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启动参数进行调整,无需重新编译内核。

    • 永久修改

      • 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”
    • 临时修改

      • 内核启动时,输入"e"进入修改启动选项界面,加入参数“default_hugepagesz=2M”,然后输入"ctrl+x"启动内核。
  2. jemalloc编译参数"--with-lg-hugepage=21"
    jemalloc支持编译参数"--with-lg-hugepage=21",替代系统的默认的hugepage size为2MB。建议使用该方法。
5. 验证

修改默认hugepage size后测试结果(sysbench使用256线程压测)如下:
 title=
测试结果显示,将hugepage size改为2MB以后,jemalloc的内存使用情况和glibc接近。

总结

该"问题"和架构无关,jemalloc作为内存管理器,如果默认hugepage size较大,会导致软件占用较大的内存,jemalloc提供了编译参数"--with-lg-hugepage=21"来降低这个影响。

由于ARM64支持更多类型的page size和hugepage size,用以提升软件的性能。所以用户在ARM64系统上使用jemalloc时,需要关注默认的page size和hugepage size,并根据具体需求做出相应的调整。

参考

https://uncp.github.io/JeMalloc/
https://www.kernel.org/doc/html/latest/arm64/hugetlbpage.html
https://github.com/memkind/memkind/blob/master/jemalloc/INSTALL.md
https://github.com/jemalloc/jemalloc/issues/2178
https://github.com/jemalloc/jemalloc/blob/dev/TUNING.md
http://www.brionas.com/2017/05/25/jemalloc源码解析-核心架构-2/
https://www.kernel.org/doc/html/v4.19/admin-guide/kernel-parameters.html?highlight=hugepagesz

与[转帖]ARM64 CentOS系统下MySQL使用jemalloc时的问题和解决方法相似的内容:

[转帖]ARM64 CentOS系统下MySQL使用jemalloc时的问题和解决方法

https://aijishu.com/a/1060000000321521 本文主要介绍在ARM64 CentOS系统下,MySQL使用jemalloc作为内存管理器时,内存占用问题的分析过程和解决方法。 Jemalloc 简介 Jemalloc是由Jason Evans在FreeBSD项目中引入

[转帖]ARM64体系结构编程与实践:基础知识

ARM64体系结构编程与实践:基础知识 原创 异步社区 2022-03-30 12:44:16 ©著作权 文章标签 寄存器 体系结构 v8 ARM64体系结构 ARM 文章分类 物联网 阅读数1570 ©著作权归作者所有:来自51CTO博客作者异步社区的原创作品,请联系作者获取转载授权,否则将追究法

[转帖]Windows 11 22H2 中文版、英文版 (x64、ARM64) 下载 (updated Jan 2023)

https://sysin.org/blog/windows-11-no-tpm/ 感谢原作者 Windows 11, version 22H2,2023 年 1 月 更新 Posted by sysin on 2023-01-22 Estimated Reading Time 11 Minutes

[转帖]docker使用buildx构建多平台(x86,arm64)构架镜像

https://blog.csdn.net/atzqtzq/article/details/128583331 配置文件激活buildx docker目前使用版本为Server Version: 20.10.7,添加配置支持buildx docker版本较低时,请升级docker版本 $ vim /

[转帖]BPF内部原理

https://aijishu.com/a/1060000000220363 LinuxKernel性能优化Arm 处理器arm64 1. 简介 Brendan最近在USENIX LISA2021大会上做了一篇关于BPF内部原理的演讲,这篇演讲把BPF的内部逻辑剖析地非常清楚,本文大部分素材来自Br

[转帖]OpenEuler的简单使用.

RPM安装 本章节主要介绍在openEuler 22.03 LTS操作系统上,通过yum命令一键安装openGauss数据库。 支持的架构和操作系统版本 x86-64 openEuler 22.03 LTS ARM64 openEuler 22.03 LTS 仅在openEuler 22.03 LT

[转帖]Ceph优化系列(四):RocksDB 使用 ARM 64 位 CRC32C 硬件优化指令

一、前言 CRC32(A cyclic redundancy check 32)应用于校验,为了保证数据的正确性,采用的一种检错手段。 CRC32C (CRC32 Castagnoli) 与 CRC32 不同的是它有多项式常数,也就是说生成的CRC表不同,而算法是一模一样. 二、内容 1. Ceph

[转帖]armv6、armv7、armv7s、armv8、armv64及其i386、x86_64区别

ARM处理器指令集 一. 苹果模拟器指令集: 指令集分析i386针对intel通用微处理器32架构的x86_64针对x86架构的64位处理器i386|x86_64是Mac处理器的指令集,i386是针对intel通用微处理器32架构的。x86_64是针对x86架构的64位处理器。 模拟器并不运行arm

[转帖]

Linux ubuntu20.04 网络配置(图文教程) 因为我是刚装好的最小系统,所以很多东西都没有,在开始配置之前需要做下准备 环境准备 系统:ubuntu20.04网卡:双网卡 网卡一:供连接互联网使用网卡二:供连接内网使用(看情况,如果一张网卡足够,没必要做第二张网卡) 工具: net-to

[转帖]

https://cloud.tencent.com/developer/article/2168105?areaSource=104001.13&traceId=zcVNsKTUApF9rNJSkcCbB 前言 Redis作为高性能的内存数据库,在大数据量的情况下也会遇到性能瓶颈,日常开发中只有时刻