0

0

c++中如何选择合适的内存分配器? (jemalloc vs tcmalloc vs mimalloc)

冰火之心

冰火之心

发布时间:2026-01-14 12:58:02

|

859人浏览过

|

来源于php中文网

原创

当出现高并发小对象分配、内存碎片严重、malloc/free成性能热点或需细粒度控制时应更换默认分配器;jemalloc重利用率与稳定性,tcmalloc重低延迟与调试支持,mimalloc重零配置低延迟与快速RSS回收。

c++中如何选择合适的内存分配器? (jemalloc vs tcmalloc vs mimalloc)

什么时候该换默认分配器?

标准库malloc(通常是 glibc 的 ptmalloc)在多数场景下够用,但一旦出现以下情况,就该考虑替换:
高并发线程频繁分配/释放小对象(如 Web 服务、游戏服务器);内存碎片严重导致 RSS 持续上涨;malloc/free 占用 profiler 热点 top 3;或需要更细粒度的内存行为控制(比如隔离不同模块的堆)。这时候换分配器不是“优化”,而是解决实际瓶颈。

jemalloc 和 tcmalloc 的核心差异在哪?

两者都主打多线程可扩展性,但设计哲学不同:
jemalloc 更强调内存利用率和长期稳定性,对大页支持好,适合长时间运行、负载波动大的服务(如数据库、Redis);
tcmalloc(Google 开源,现为 gperftools 的一部分)延迟更低,尤其在小对象分配上更快,但可能略多占用内存;
tcmalloc 默认启用 heap profilercpu profiler 支持,调试友好;jemallocmalloc_stats_print() 输出更结构化,适合监控集成;
• 在 Linux 上,tcmallocMAP_HUGETLB 支持较弱,而 jemalloc 可通过 opt.lg_chunk 显式控制 chunk 大小。

mimalloc 为什么近年被广泛采用?

mimalloc微软研究院推出的现代分配器,目标是「低延迟 + 低内存开销 + 零配置」:
• 它用固定大小的 segment(默认 64 MiB)替代传统 arena,天然减少跨线程竞争;
• 小对象(≤ 256 B)走 thread-local free list,几乎无锁
• 内存回收更激进,RSS 下降比 jemalloc/tcmalloc 更快;
• 编译时只需链接 -lmimalloc,无需 LD_PRELOAD 或环境变量(虽然也支持);
• 注意:它不兼容 malloc_usable_size() 的语义(返回值可能小于申请值),若代码依赖该行为需改写;
• 在 C++ 异常展开期间调用 free 的路径上,mimalloc 的 unwind 安全性比早期 tcmalloc 更可靠。

实操建议:怎么快速验证效果?

别直接上线换,先做三件事:
• 用 LD_PRELOAD=/path/to/libjemalloc.so ./your_program 启动,观察 /proc/PID/status 中的 VmRSSperf record -e 'syscalls:sys_enter_brk,syscalls:sys_enter_mmap' -g 的系统调用频次;
• 对比 malloc_stats_print()(jemalloc)、TCMalloc_Printer(tcmalloc)或 mi_stats_print()(mimalloc)输出中的 allocated/mapped 比值;
• 如果程序用 std::vectorstd::string 极多,记得重载全局 operator new —— 否则分配器只生效于显式 malloc 调用;
• CI 中加个轻量 benchmark(比如 100 线程各循环分配 10k 次 64B 对象),用 time -vMaximum resident set size 和用户时间。

Solvely
Solvely

AI学习伴侣,数学解体,作业助手,家教辅导

下载

立即学习C++免费学习笔记(深入)”;

// 示例:强制 std::vector 使用 mimalloc
#include 
// 或编译时加 -D MI_MALLOC_OVERRIDE

选哪个没有银弹。短生命周期、高吞吐服务(如 API 网关)倾向 mimalloc;已有成熟监控体系且追求稳定性的后台服务,jemalloc 更稳妥;已深度集成 gperftools 生态的项目,继续用 tcmalloc 成本最低。真正容易被忽略的是:分配器不能掩盖设计问题——如果每秒 new 几十万对象,先想能不能用对象池或 arena allocator。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

315

2023.08.02

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

387

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

571

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

387

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

571

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

480

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

143

2025.12.24

Java 并发编程高级实践
Java 并发编程高级实践

本专题深入讲解 Java 在高并发开发中的核心技术,涵盖线程模型、Thread 与 Runnable、Lock 与 synchronized、原子类、并发容器、线程池(Executor 框架)、阻塞队列、并发工具类(CountDownLatch、Semaphore)、以及高并发系统设计中的关键策略。通过实战案例帮助学习者全面掌握构建高性能并发应用的工程能力。

60

2025.12.01

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

34

2026.01.14

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.1万人学习

Git 教程
Git 教程

共21课时 | 2.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号