深入理解 jemalloc:從內存分配機制到技術選型

在高性能服務(如數據庫、緩存、JVM)的底層優化中,內存分配效率直接影響系統整體性能。本文將從操作系統底層的malloc機制切入,詳解 jemalloc 的設計理念、開源應用場景、實戰案例,技術選型分析

一、操作系統底層的內存分配機制:從malloc說起

malloc是 C 標準庫提供的動態內存分配接口,但其底層依賴操作系統的內存管理機制實現。要理解malloc的工作原理,需先明確 “用戶態內存分配” 與 “內核態內存管理” 的協作關系。

1.1 malloc的底層依賴:內核態內存接口

malloc本身不直接管理物理內存,而是通過調用操作系統內核提供的內存申請接口獲取 “大塊內存”,再在用戶態將其拆分為小塊分配給應用。不同操作系統的內核接口略有差異:

  • Linux:通過brk()/sbrk()(調整進程數據段邊界)或mmap()(映射匿名內存區域)申請內存;
  • Windows:通過VirtualAlloc()申請虛擬內存;
  • macOS:通過vm_allocate()或mmap()實現。

以 Linux 為例,malloc的核心流程如下:

  1. 當應用調用malloc(100)時,malloc先檢查 “用戶態內存池”(已從內核申請但未分配的內存)是否有足夠空間;
  2. 若內存池有空間,直接從池中分拆 100 字節返回給應用;
  3. 若內存池無空間,調用mmap()向內核申請一塊 “大塊內存”,加入內存池后再分拆分配;
  4. 當應用調用free()釋放內存時,malloc將內存歸還給用戶態內存池,若內存池中有連續的 “大塊空閑內存”,會調用munmap()歸還給內核(避免內存泄漏)。

記憶 我要吃一片蘋果,老媽給我拿來一個蘋果,要就直接拿,一段時間后老媽看到蘋果,如果吃過就放著(歸還用戶內存池),沒吃過就回收進冰箱(回收進內核,避免內存泄露)

1.2 傳統malloc的痛點:性能與碎片問題

標準庫malloc(GNU C 庫的ptmalloc2)雖能滿足基礎需求,但在高并發、大內存、頻繁分配 / 釋放場景下存在明顯缺陷:

  1. 線程安全開銷大:為保證多線程安全,ptmalloc2使用全局鎖,高并發時線程競爭鎖會導致性能瓶頸;
  2. 內存碎片嚴重
  • 內部碎片:分配的內存塊大于實際需求(如申請 100 字節,分配 128 字節對齊),浪費空間;
  • 外部碎片:頻繁分配 / 釋放后,內存池中存在大量 “小塊空閑內存”,無法滿足大塊內存申請需求;
  1. 內存利用率低:對大內存(如 GB 級)或小塊內存(如幾十字節)的分配策略優化不足,易導致內存浪費;
  2. GC 友好性差:分配的內存塊地址分散,不便于 CPU 緩存命中,且內存回收時難以批量釋放。

這些痛點在高性能服務(如 Redis、MySQL、JVM)中會被放大,因此需要更高效的內存分配器 ——jemalloc 應運而生。

二、jemalloc 介紹:特性、作業模式與開源應用

jemalloc(Jealloc)是由 Jason Evans 開發的高性能內存分配器,最初為 FreeBSD 系統設計,后因優異的性能被廣泛應用于各類開源項目。其核心目標是 “低延遲、低碎片、高并發友好”。

2.1 jemalloc 的核心特性

  1. 分級鎖機制
  • 摒棄全局鎖,為每個線程分配獨立的 “線程本地緩存”,線程分配內存時優先從本地緩存獲取,減少鎖競爭;
  • 僅當本地緩存無可用內存時,才通過 “中央緩存” 或 “堆” 申請,且中央緩存使用細粒度鎖(如按內存大小分級加鎖),進一步降低并發開銷。
  1. 內存塊大小分級
  • 將內存塊按大小分為 “小塊(<2KB)、中塊(2KB~4MB)、大塊(>4MB)”,不同級別使用不同的分配策略:
  • 小塊:通過 “競技場(Arena)” 管理,按固定大小(如 8 字節、16 字節、32 字節)對齊,減少內部碎片;
  • 中塊:通過 “slabs( slab 分配器)” 管理,將大塊內存拆分為固定大小的 slab,批量分配;
  • 大塊:直接通過mmap()向內核申請,避免中間層開銷。
  1. 低內存碎片設計
  • 內部碎片:通過動態對齊算法,根據申請大小選擇最接近的 “標準塊大小”,最小化浪費(如申請 100 字節,分配 128 字節,碎片率 28%,優于ptmalloc2的 50%);
  • 外部碎片:通過 “內存合并” 和 “競技場隔離”,將不同大小的內存塊分開管理,減少碎片累積。
  1. 內存監控與調試
  • 內置內存使用統計功能,可實時查看內存分配、碎片率、緩存命中率等指標;
  • 支持內存泄漏檢測和內存越界檢測,便于問題排查。

2.2 jemalloc 的作業模式

jemalloc 的作業流程可分為 “內存分配” 和 “內存釋放” 兩個階段,核心是 “線程本地緩存→中央緩存→堆” 的三級內存管理:

(1)內存分配流程

  1. 線程調用je_malloc(size)時,先檢查 “線程本地緩存(TC)”:
  • 若 TC 中有對應大小的空閑內存塊,直接返回并更新 TC 狀態;
  • 若 TC 中無可用內存,向 “中央緩存(Central Cache)” 申請;
  1. 中央緩存按內存塊大小分級管理,若有可用內存,批量分配給 TC(如一次性分配 10 個同大小的內存塊);
  2. 若中央緩存也無可用內存,向 “堆(Heap)” 申請:
  • 小塊 / 中塊:從 “競技場(Arena)” 中分配 slab,拆分為固定大小的內存塊;
  • 大塊:直接調用mmap()向內核申請,返回獨立的內存塊。

(2)內存釋放流程

  1. 線程調用je_free(ptr)時,先將內存塊歸還給 TC;
  2. 當 TC 中某類大小的內存塊數量超過閾值(如 20 個),批量歸還給中央緩存;
  3. 中央緩存定期檢查空閑內存塊,若某類大小的空閑塊數量過多,將其歸還給堆:
  • 小塊 / 中塊:合并到 slab 中,若 slab 完全空閑,歸還給競技場;
  • 大塊:調用munmap()歸還給內核。

2.3 jemalloc 的開源項目引用

由于優異的性能,jemalloc 已成為眾多高性能開源項目的默認內存分配器,典型案例包括:

  1. Redis
  • 從 Redis 5.0 開始,默認使用 jemalloc 替代ptmalloc2,解決高并發下的內存碎片和鎖競爭問題;
  • 實測表明,Redis 使用 jemalloc 后,內存碎片率從ptmalloc2的 30%+ 降至 10% 以下,QPS 提升 15%~20%。
  1. MySQL
  • InnoDB 存儲引擎支持通過--with-jemalloc編譯選項集成 jemalloc,優化緩沖池(Buffer Pool)的內存分配效率;
  • 尤其在大內存(如 128GB+)場景下,jemalloc 的低碎片特性可減少 InnoDB 的內存浪費,提升查詢性能。
  1. MongoDB
  • 自 MongoDB 3.2 起,默認使用 jemalloc 管理內存,解決文檔存儲中 “小塊內存頻繁分配 / 釋放” 導致的碎片問題;
  • 支持通過mongod --setParameter enableJemalloc=true開啟,內存利用率提升 25% 以上。
  1. FreeBSD/Linux 內核
  • FreeBSD 系統將 jemalloc 作為默認內存分配器,替代傳統的ptmalloc;
  • Linux 內核的部分子系統(如內存管理模塊)也引入 jemalloc 的設計理念,優化內核態內存分配。
  1. Nginx
  • 通過第三方模塊ngx_http_jemalloc_module集成 jemalloc,優化高并發請求下的內存分配延遲;
  • 尤其在反向代理場景中,可減少因內存碎片導致的 Nginx 進程內存膨脹。

三、jemalloc 實戰:應用案例與 JVM 集成

3.1 JVM 如何集成并使用 jemalloc

JVM默認使用自身實現的內存分配器

  1. Java 堆(Heap)
    這一大塊區域完全由 JVM 自己管,不依賴操作系統 malloc
    HotSpot 的默認實現用了 “TLAB + 分代/分區的專用分配器”
    • 每條線程先在 Eden/Current 區域里拿到一個 TLAB(Thread-Local Allocation Buffer)
    • 對象分配就在這個 TLAB 里做 指針碰撞(bump-the-pointer)
    • TLAB 用光以后再向 JVM 的 內存管理器(GenCollectedHeap / G1CollectedHeap / ZCollectedHeap 等) 申請一塊新的。
      所以這部分跟 glibc malloc、jemalloc 都沒關系,是 JVM 內部定制的。
  1. 非堆(Native / C-Heap)
    任何 HotSpot 里用 C/C++ 寫的代碼——包括:
    • 類元數據(Metaspace)、
    • JIT 編譯后的代碼(Code Cache)、
    • DirectByteBuffer、
    • JNI 調用時你自己 malloc/new 的內存、
    • JVM 內部各種數據結構(Arena、Chunk、Handle 等)
      最終都會落到 操作系統的 C 庫 malloc/free(Linux 上默認是 glibc ptmalloc)。

(1)JVM 集成 jemalloc 的場景

JVM 中的 “直接內存”默認使用malloc分配,若集成 jemalloc,可解決以下問題:

  1. 高并發下Direct Buffer頻繁分配 / 釋放導致的鎖競爭;
  2. 直接內存的內存碎片問題(尤其在大數據框架如 Spark/Flink 中,直接內存使用量可達 GB 級);
  3. 直接內存回收延遲導致的內存泄漏(jemalloc 的內存監控可快速定位泄漏點)。

(2)JVM 集成 jemalloc 的配置步驟

  1. 確保 jemalloc 庫已安裝(如/usr/local/lib/libjemalloc.so);
  2. 啟動 JVM 時,通過-Djava.library.path指定 jemalloc 庫路徑,并通過LD_PRELOAD強制替換默認malloc:
exportLD_PRELOAD=/usr/local/lib/libjemalloc.so
exportMALLOC_CONF="stats_print:true,lg_chunk:20" # 開啟內存統計
spark-submit \--master yarn \--conf spark.executor.extraJavaOptions="-Djava.library.path=/usr/local/lib" \--classcom.example.SparkApp \app.jar
  1. 驗證 jemalloc 是否生效:
  • 查看 JVM 進程的內存分配器:lsof -p <pid> | grep jemalloc,若顯示libjemalloc.so,則集成成功;
  • 通過 jemalloc 的統計接口查看直接內存分配情況:在代碼中調用je_malloc_stats_print()(需通過 JNI 調用)。

(3)JVM 使用 jemalloc 的性能收益

在 Flink 實時計算場景中,實測集成 jemalloc 后:

  • 直接內存碎片率從 35% 降至 8%;
  • 直接內存分配延遲從平均 500ns 降至 150ns;
  • Flink 作業的 GC 停頓時間減少 20%(因直接內存回收更高效,減少對 JVM 堆的影響)。

四、jemalloc 原理與技術選型分析

4.1 jemalloc 的核心原理

jemalloc 的優異性能源于其 “分級管理、隔離設計、并發優化” 三大核心原理:

(1)分級內存管理:從線程到堆的三級緩存

jemalloc 通過 “線程本地緩存(TC)→中央緩存(CC)→堆(Heap)” 的三級結構,減少內存分配的 “路徑長度”:

  • 線程本地緩存(TC):每個線程獨立擁有,無鎖分配,適合小塊內存(<2KB),命中率可達 90%+;
  • 中央緩存(CC):全局共享,按內存塊大小分級管理,使用細粒度鎖(如每個大小級別一個鎖),減少鎖競爭;
  • 堆(Heap):由多個 “競技場(Arena)” 組成,每個 Arena 管理一塊連續內存,不同 Arena 可并行分配,支持大規模內存(>4MB)。

(2)競技場隔離(Arena Isolation):減少碎片與競爭

jemalloc 將堆劃分為多個獨立的 “競技場(Arena)”,每個 Arena 管理一塊內存區域(默認大小為 4MB),核心優勢:

  1. 不同線程可綁定到不同 Arena,減少跨線程的內存競爭;
  2. 不同大小的內存塊在不同 Arena 中管理(如小塊內存用 Arena 0,中塊用 Arena 1),避免碎片交叉累積;
  3. 當某一 Arena 的內存碎片過高時,可單獨進行 “碎片整理”,不影響其他 Arena。

(3)Slab 分配器:優化中塊內存分配

對于中塊內存(2KB~4MB),jemalloc 使用 “Slab 分配器” 管理:

  1. 將 Arena 中的大塊內存(如 4MB)拆分為固定大小的 Slab(如 Slab 大小為 2KB);
  2. 每個 Slab 包含多個 “內存塊”(如 2KB 的 Slab 包含 1 個 2KB 塊,或 2 個 1KB 塊);
  3. 分配中塊內存時,直接從對應大小的 Slab 中獲取,釋放時歸還給 Slab,避免頻繁向內核申請內存。

4.2 技術選型:為什么選擇 jemalloc?

在內存分配器選型中,需對比ptmalloc2(GNU C 庫)、TCMalloc(Google)、jemalloc 三者的核心差異,jemalloc 的優勢在 “高并發、大內存、低碎片” 場景中尤為突出。

(1)三者核心特性對比

特性

jemalloc

TCMalloc

ptmalloc2(GNU C)

并發性能

分級鎖 + 線程本地緩存,無鎖分配占比 90%+

線程本地緩存,中央緩存細粒度鎖

全局鎖,高并發下性能瓶頸明顯

內存碎片率

低(10% 以下)

中(15%~20%)

高(25%~30%)

內存利用率

高(動態對齊 + Slab 優化)

中(固定大小塊)

低(靜態對齊)

大內存支持

優(直接 mmap+Arena 隔離)

中(支持但碎片較多)

差(易產生外部碎片)

調試與監控

內置統計 + 泄漏檢測

需依賴第三方工具

基本統計,功能薄弱

跨平臺支持

支持 Linux/FreeBSD/macOS

支持 Linux/Windows

支持全平臺,但性能差異大

開源項目適配度

高(Redis/MySQL/MongoDB

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

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

相關文章

websoket使用記錄

1.項目使用記錄1.醫療項目中渲染回收柜溫濕度&#xff0c;需要實時更新2.回收柜安瓿回收和余液回收時&#xff0c;需要前端發送指令給回收柜&#xff0c;比如開門、關門等。還需要收到回收柜結果&#xff0c;比如回收的藥品信息等。我項目中用的是瀏覽器自帶的websoket&#xf…

DevOps篇之通過GitLab CI 流水線實現k8s集群中helm應用發布

一. 設計思路 構建一個 GitLab CI 流水線&#xff0c;并且要集成到 K8s 集群中的 Helm 應用發布流程。首先&#xff0c;需要了解 GitLab CI 的基本結構&#xff0c;比如.gitlab-ci.yml 文件的配置&#xff0c;包括 stages、jobs、變量設置等。然后&#xff0c;結合之前討論的 H…

詳盡 | Deeplabv3+結構理解

https://arxiv.org/pdf/1802.02611.pdf https://link.springer.com/chapter/10.1007/978-3-319-10578-9_23 目錄 Deeplabv3 Encoder部分 Decoder部分 補充摘要 SPP 空間金字塔池化層模塊 Dilated/Atrous Conv 空洞卷積 Deeplabv3 deeplab-v3是語義分割網絡&#xff0c;組…

【51單片機】【protues仿真】基于51單片機音樂盒(8首歌曲)系統

目錄 一、主要功能 二、使用步驟 三、硬件資源 四、軟件設計 五、實驗現象 一、主要功能 1、數碼管顯示當前歌曲序號 2、按鍵切換歌曲和播放暫停? 3、內置8首音樂 二、使用步驟 基于51單片機的音樂盒是一種能夠存儲和播放多首歌曲的電子設備&#xff0c;通過定時器產…

@ZooKeeper 詳細介紹部署與使用詳細指南

文章目錄 **ZooKeeper 詳細介紹、部署與使用** 1. 概述 & 核心介紹 1.1 什么是 ZooKeeper? 1.2 核心特性 1.3 核心概念 1.4 典型應用場景 2. 部署 (以 3 節點集群為例) 2.1 環境準備 2.2 安裝步驟 (在所有節點執行) 2.3 啟動與停止集群 2.4 防火墻配置 (如果開啟) 3. 基本…

騰訊Hunyuan-MT-7B翻譯模型完全指南:2025年開源AI翻譯的新標桿

&#x1f3af; 核心要點 (TL;DR) 突破性成就&#xff1a;騰訊混元MT-7B在WMT25全球翻譯競賽中獲得30/31項第一名雙模型架構&#xff1a;Hunyuan-MT-7B基礎翻譯模型 Hunyuan-MT-Chimera-7B集成優化模型廣泛語言支持&#xff1a;支持33種語言互譯&#xff0c;包括5種中國少數民…

Web 集群高可用全方案:Keepalived+LVS (DR) 負載均衡 + Apache 服務 + NFS 共享存儲搭建指南

文章目錄Keepalived LVS&#xff08;DR&#xff09; Apache NFS項目背景業務場景與核心需求傳統架構的痛點與局限技術方案的選型邏輯項目價值與預期目標項目實踐項目環境基礎配置配置 router配置免密登錄-可選配置 nfs配置 web配置 LVS-RS配置 HA 和 LVS-DS配置 ha1配置 ha2測…

Prometheus監控預警系統深度解析:架構、優劣、成本與競品

目錄 一、Prometheus是什么&#xff1f;核心定位與架構 二、競品分析&#xff08;Prometheus vs. Zabbix vs. Nagios vs. Commercial SaaS&#xff09; 三、部署成本分析 四、服務器資源消耗分析 五、給您的最終建議 一、Prometheus是什么&#xff1f;核心定位與架構 Prom…

Nginx反向代理及配置

Nginx反向代理 二級域名系統 顧名思義&#xff0c;我們有很多的這個不同的二級域名的用戶來訪問我們&#xff0c;比如說微博。它有一個主域名weibo.com。如果我叫一鳴,申請了一個微博&#xff0c;然后我就可以在微博這個主系統上申請一個二級域名來訪問我微博的主頁&#xff0…

嵌入式系統通信總線全景探秘:從板內到云端

引言 在嵌入式系統設計中&#xff0c;選擇合適的通信總線是決定系統性能、成本和可靠性的關鍵因素。從簡單的芯片間通信到復雜的工業網絡&#xff0c;不同的總線技術各司其職&#xff0c;形成了嵌入式世界的"交通網絡"。本文將深入探討五種經典且重要的通信技術&…

2022版Unity創建時沒有2D燈光(2D Light),沒有Global LIght2D怎么辦?

簡單來說就是你的渲染管線沒有升級到URP管線&#xff0c;所以才沒有這些2D燈光 如果你的創建燈光和我一樣&#xff0c;沒有紅線劃掉的部分&#xff0c;說明你和我的問題一樣&#xff0c;看下面的教程可以解決。 1. 確保Unity版本 確保你的Unity版本至少為2019.4或更高版本&…

技術小白如何快速的了解opentenbase?--把握四大特色

1.基本介紹 作為一名計算機專業相關背景的學生&#xff0c;我們或多或者接觸過一些數據庫&#xff0c;對于數據庫肯定是有所了解的&#xff1b; 你可能學習的是和微軟的sql server這樣的數據庫&#xff1b; 你可能接觸的更多的是企業級項目開發里面使用的這個mysql數據庫&#…

企業微信AI落地:如何選擇企業微信服務商?

現在企業用企業微信做客戶運營&#xff0c;最怕的不是“沒AI工具”&#xff0c;而是“AI用不起來”——要么功能不貼業務場景&#xff0c;員工嫌麻煩不用&#xff1b;要么回復不專業&#xff0c;客戶體驗差&#xff1b;要么數據不同步&#xff0c;管理者看不到效果。其實解決這…

【學Python自動化】 11 標準庫簡介 —— 第二部分

一、格式化輸出 reprlib 模塊 提供定制版 repr()&#xff0c;縮略顯示大型或深層嵌套對象import reprlib reprlib.repr(set(supercalifragilisticexpialidocious)) # "{a, c, d, e, f, g, ...}"pprint 模塊 美化輸出&#xff0c;添加換行和縮進顯示復雜數據結構impor…

【Kubernetes】知識點2

15. 什么是Pod的根容器&#xff1f;答&#xff1a;Pod 的根容器是每個 Pod 中默認存在的一個特殊容器pause容器&#xff0c;有時也稱為infra容器&#xff0c;它是Pod 啟動時創建的第一個容器&#xff0c;也是整個 Pod中所有容器的 “父容器”。其核心作用是為 Pod 內的所有容器…

視頻增強AI哪個效果好?實戰對比幫你找到最適合的工具

hitpaw 牛小影hitpaw 牛小影在處理低質量視頻時&#xff0c;我們經常會遇到畫面模糊、噪點過多、分辨率不足等問題&#xff0c;比如老舊視頻資料修復、監控錄像清晰化、手機拍攝視頻畫質提升等。這時候&#xff0c;一款好用的視頻增強AI軟件就成了剛需。下面就為大家盤點幾款效…

C#工作流示例(WorkflowCore)

using Microsoft.Extensions.DependencyInjection; using WorkflowCore.Interface; using WorkflowCore.Models;namespace LeaveRequestWorkflow {// 請假申請單public class LeaveBill{/// <summary>/// 申請人/// </summary>public string EmployeeName { get; s…

兩個子進程之間使用命名pipe

兩個子進程間可以使用命名管道&#xff0c;非常簡單。管道如果文件一樣存在硬盤中&#xff0c;使用ls可以查看&#xff0c;管道文件0字節。使用fork函數分別創建兩個子進程。 一個負責讀數據&#xff0c;一個負責寫數據。 #define _GNU_SOURCE #include <stdio.h> #inclu…

第一講、Kafka 初識與環境搭建

一、Kafka 是什么&#xff1f; Apache Kafka 是一個分布式的消息隊列&#xff08;Message Queue&#xff09;與流處理平臺。 它最早由 LinkedIn 開發&#xff0c;后來捐贈給 Apache 基金會&#xff0c;現已廣泛應用于日志收集、實時數據管道和大數據處理。 Kafka 的特點&…

Conda相關的用法

1、背景 此文主要記錄conda的一些用法&#xff0c;大部分命令來自ai搜索以及自己的理解。 2、安裝conda 2.1 選擇 conda 版本 2.1.1 Anaconda 含有 Conda 大量科學計算包&#xff08;NumPy、Pandas、Matplotlib 等&#xff09;適合數據科學、機器學習初學者下載地址&…