centos下使用jemalloc解決Mysql內存泄漏問題

參考: MySQL bug:https://bugs.mysql.com/bug.php?id=83047&tdsourcetag=s_pcqq_aiomsg?

    https://github.com/jemalloc/jemalloc/blob/dev/INSTALL.md

(1)ptmalloc?是glibc的內存分配管理

(2)tcmalloc?是google的內存分配管理模塊

(3)jemalloc?是BSD的提供的內存分配管理 (可以使用jemalloc優化Nginx)

三者jemalloc和tcmalloc的性能不分伯仲,而ptmalloc則要低一些

1、下載最新版jemalloc

git clone https://github.com/jemalloc/jemalloc

cd?jemalloc

[root@bogon jemalloc]# cat VERSION
5.1.0-108-gc4063ce439523d382f2dfbbc5bf6da657e6badb0

2、安裝步驟:

./autogen.sh

./configure?

make?

make install

[root@bogon jemalloc]# make install

/usr/bin/install -c -d /usr/bin
/usr/bin/install -c -m 755 bin/jemalloc-config /usr/bin
/usr/bin/install -c -m 755 bin/jemalloc.sh /usr/bin
/usr/bin/install -c -m 755 bin/jeprof /usr/bin
/usr/bin/install -c -d /usr/include/jemalloc
/usr/bin/install -c -m 644 include/jemalloc/jemalloc.h /usr/include/jemalloc
/usr/bin/install -c -d /usr/lib
/usr/bin/install -c -m 755 lib/libjemalloc.so.2 /usr/lib
ln -sf libjemalloc.so.2 /usr/lib/libjemalloc.so
/usr/bin/install -c -d /usr/lib
/usr/bin/install -c -m 755 lib/libjemalloc.a /usr/lib
/usr/bin/install -c -m 755 lib/libjemalloc_pic.a /usr/lib
/usr/bin/install -c -d /usr/lib/pkgconfig
/usr/bin/install -c -m 644 jemalloc.pc /usr/lib/pkgconfig
/usr/bin/install -c -d /usr/share/doc/jemalloc
/usr/bin/install -c -m 644 doc/jemalloc.html /usr/share/doc/jemalloc
/usr/bin/install: cannot stat ‘doc/jemalloc.html’: No such file or directory
make: *** [install_doc_html] Error 1
[root@bogon jemalloc]#

默認安裝目錄:

PREFIX???????????? : /usr/local
BINDIR???????????? : /usr/local/bin
DATADIR??????????? : /usr/local/share
INCLUDEDIR???????? : /usr/local/include
LIBDIR???????????? : /usr/local/lib
MANDIR???????????? : /usr/local/share/man

3、配置mysqld使用jemalloc,需要將配置寫到[mysqld_safe] section

[mysqld_safe]
malloc-lib=/usr/local/lib/libjemalloc.so

4. 如果直接使用sqld啟動,

export LD_PRELOAD=/usr/local/lib/libjemalloc.so

然后啟動sqld

5、查看jemalloc是否生效

lsof -n |grep jemalloc

[root@localhost mysql3306]# lsof -n |grep jemalloc
bash????? 11223???????????????? root? cwd?????? DIR????????????? 253,0????? 4096????? 35178 /software/jemalloc
mysqld??? 17475??????????????? mysql? mem?????? REG????????????? 253,0?? 4291512?? 18480172 /usr/lib/libjemalloc.so.2
mysqld??? 17475 17482????????? mysql? mem?????? REG????????????? 253,0?? 4291512?? 18480172 /usr/lib/libjemalloc.so.2
mysqld??? 17475 17483????????? mysql? mem?????? REG????????????? 253,0?? 4291512?? 18480172 /usr/lib/libjemalloc.so.2
mysqld??? 17475 17484????????? mysql? mem?????? REG????????????? 253,0?? 4291512?? 18480172 /usr/lib/libjemalloc.so.2

顯示以上信息說明mysql已經成功加載jemalloc

或者

使用jemalloc(或tcmalloc)優化MYSQL(安裝步驟)

malloc

  1. wget 
    tar xjf jemalloc-3.4.0.tar.bz2
    cd jemalloc-3.4.0
    ./configure --prefix=/usr/local/jemalloc --libdir=/usr/local/lib make && make install
    echo '/usr/local/lib' > /etc/ld.so.conf.d/local.conf
    ldconfig
    [root@host-192-168-1-56 mysql]# cp /usr/local/lib/libjemalloc.so /usr/lib64/mysql/libjemalloc.so

mysql使用jemalloc

  1. 修改配置文件
  2. [mysqld_safe]
    malloc-lib=/usr/lib64/mysql/libjemalloc.so ? ? ? ? ? ? ###指定libjemalloc.so 即可

重啟mysql檢查是否生效

  1. [root@host-192-168-1-56 mysql]# lsof -n | grep jemalloc
    mysqld ? ? 6032 ? ? mysql ?mem ? ? ? REG ? ? ? ? ? ? ?252,1 ? 4781206 ? ? 320288 /usr/lib64/mysql/libjemalloc.so

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,并根據具體需求做出相應的調整。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/43640.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/43640.shtml
英文地址,請注明出處:http://en.pswp.cn/news/43640.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【設計模式】模板方法模式(Template Method Pattern)

23種設計模式之模板方法模式(Template Method Pattern) 基本概念 模板方法模式是一種行為型設計模式,它定義了一個算法骨架,將某些算法步驟的實現延遲到子類中。 這樣可以使得算法的框架不被修改,但是具體的實現可以…

Django

一 django 安裝 1. **安裝 Django:** 首先,確保您已經安裝了 Python 和 pip(Python 包管理器)。然后,在命令行中運行以下命令來安裝 Django: bashpip install Django 2. **創建項目:** …

Electron-builder打包和自動更新

前言 文本主要講述如何為 electron 打包出來軟件配置安裝引導和結合 github 的 release 配置自動更新。 electron-builder 是將 Electron 工程打包成相應平臺的軟件的工具,我的工程是使用 electron-vite 構建的,其默認集成了 electron-builder &#x…

中大型無人機遠程VHF語音電臺系統方案

方案背景 中大型無人機在執行飛行任務時,特別是在管制空域飛行時地面航管人員需要通過語音與無人機通信。按《無人駕駛航空器飛行管理暫行條例》規定,中大型無人機應當進行適航管理。物流無人機和載人eVTOL都將進行適航管理,所以無人機也要有…

Unity 工具 之 Azure 微軟SSML語音合成TTS流式獲取音頻數據的簡單整理

Unity 工具 之 Azure 微軟SSML語音合成TTS流式獲取音頻數據的簡單整理 目錄 Unity 工具 之 Azure 微軟SSML語音合成TTS流式獲取音頻數據的簡單整理 一、簡單介紹 二、實現原理 三、實現步驟 四、關鍵代碼 一、簡單介紹 Unity 工具類,自己整理的一些游戲開發可…

Qt creator之對齊參考線——新增可視化縮進功能

Qt creator隨著官方越來越重視,更新頻率也在不斷加快,今天無意中發現qt creator新版有了對齊參考線,也稱可視化縮進Visualize Indent,默認為啟用狀態。 下圖為舊版Qt Creator顯示設置欄: 下圖為新版本Qt Creator顯示設…

Day14 01-Shell腳本編程詳解

文章目錄 第一章 Shell編程【重點】1.1. Shell的概念介紹1.1.1. 命令解釋器4.1.1.2. Shell腳本 1.2. Shell編程規范1.2.1. 腳本文件的結構1.2.2. 腳本文件的執行 1.3. Shell的變量1.3.1. 變量的用法1.3.2. 變量的分類1.3.3. 局部變量1.3.4. 環境變量1.3.5. 位置參數變量1.3.6. …

Python入門【內存管理機制、Python緩存機制、垃圾回收機制、分代回收機制】(三十二)

👏作者簡介:大家好,我是愛敲代碼的小王,CSDN博客博主,Python小白 📕系列專欄:python入門到實戰、Python爬蟲開發、Python辦公自動化、Python數據分析、Python前后端開發 📧如果文章知識點有錯誤…

LeetCode150道面試經典題-- 存在重復元素 II(簡單)

1.題目 給你一個整數數組 nums 和一個整數 k &#xff0c;判斷數組中是否存在兩個 不同的索引 i 和 j &#xff0c;滿足 nums[i] nums[j] 且 abs(i - j) < k 。如果存在&#xff0c;返回 true &#xff1b;否則&#xff0c;返回 false 。 2.示例 示例 1&#xff1a; 輸…

CSS中的字體屬性有哪些值,并分別描述它們的作用。

聚沙成塔每天進步一點點 ? 專欄簡介? font-style? font-weight? font-size? font-family? font-variant? line-height? letter-spacing? word-spacing? font? 寫在最后 ? 專欄簡介 前端入門之旅&#xff1a;探索Web開發的奇妙世界 記得點擊上方或者右側鏈接訂閱本專…

JS中對象數組深拷貝方法

structuredClone() JavaScript 中提供了一個原生 API 來執行對象的深拷貝&#xff1a;structuredClone。它可以通過結構化克隆算法創建一個給定值的深拷貝&#xff0c;并且還可以傳輸原始值的可轉移對象。 當對象中存在循環引用時&#xff0c;仍然可以通過 structuredClone()…

過濾字符,繞過

構造不包含字母和數字的webshell <?phpecho "A"^""; ?>運行結果為! 代碼中對字符"A"和字符”"進行了異或操作。在PHP中&#xff0c;兩個變量進行異或時&#xff0c;先會將字符串轉換成ASCII值&#xff0c;再將ASCII值轉換成二進制…

容器docker安裝及應用

目錄 二進制安裝docker應用啟動docker拉取鏡像查看當前主機鏡像查看鏡像詳細信息運行容器 二進制安裝docker 環境 centos 7 [rootlocalhost ~]# mkdir /data [rootlocalhost ~]# wget -P /data/ https://download.docker.com/linux/static/stable/x86_64/docker-18.03.1-ce.t…

【聲波】聲波在硼酸、硫酸鎂 (MgSO4) 和純水中的吸收研究(Matlab代碼實現)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;歡迎來到本博客????&#x1f4a5;&#x1f4a5; &#x1f3c6;博主優勢&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客內容盡量做到思維縝密&#xff0c;邏輯清晰&#xff0c;為了方便讀者。 ??座右銘&a…

MAC 命令行啟動tomcat的詳細介紹

MAC 命令行啟動tomcat MAC 命令行啟動tomcat的詳細介紹 一、修改授權 進入tomcat的bin目錄,修改授權 1 2 3 ? bin pwd /Users/yp/Documents/workspace/apache-tomcat-7.0.68/bin ? bin sudo chmod 755 *.sh sudo為系統超級管理員權限.chmod 改變一個或多個文件的存取模…

2.js中attr()用來修改或者添加屬性或者屬性值

attr()可以用來修改或者添加屬性或者屬性值 例&#xff1a;<input type"button" class"btn btn-info" id"subbtn" style"font-size:12px" value"我也說一句"/>1.如果想獲取input中value的值 $(#subbtn).attr(value);…

ASP.NET Core中路由規則匹配

RESTful約束&#xff0c;如果在一個控制器里面有多個Get、Post...的操作 1、在一個控制器里面可以定義多個API方法 2、通過路由規則來區分 /// <summary> /// 獲取用戶信息 /// </summary> /// <param name"user"></param> /// <returns…

c++ | 字節轉換 | 字長 | 機器位數

為什么有的時候腦子轉不過來&#xff1f;&#xff1f; 為什么要對字節、機器長啊、位啊都要門清 位數 一般的就是指計算機的位數&#xff0c;比如64位/32位&#xff0c;更簡單的理解&#xff0c;計算機就是在不停的做二進制的計算&#xff0c;比如32位計算機&#xff0c;在長…

[保研/考研機試] KY26 10進制 VS 2進制 清華大學復試上機題 C++實現

題目鏈接&#xff1a; 10進制 VS 2進制http://www.nowcoder.com/share/jump/437195121691738172415 描述 對于一個十進制數A&#xff0c;將A轉換為二進制數&#xff0c;然后按位逆序排列&#xff0c;再轉換為十進制數B&#xff0c;我們稱B為A的二進制逆序數。 例如對于十進制…

算法基礎課——基礎算法(模板整理)

快速排序 快速排序 #include <iostream> #include <algorithm> using namespace std; int n; int s[100000]; int main() {cin>>n;for(int i0;i<n;i){cin>>s[i];}sort(s,sn);for(int i0;i<n;i){cout<<s[i]<<" ";}cout<…