推荐个C++高性能内存分配器

作者:程序喵大人日期:2025/11/22

博主介绍:程序喵大人

在现代多线程应用程序中,高效的内存管理至关重要。Google开发的TCMalloc(Thread-Caching Malloc)正是一个为此设计的内存分配器,它通过减少锁竞争和优化内存使用,提供了卓越的性能和可扩展性。

本文将详细介绍TCMalloc的工作原理、核心组件、使用方法以及调优技巧,帮助C++开发工程师更好地理解和利用这一工具。

一、TCMalloc简介

TCMalloc,全称Thread-Caching Malloc,是Google开发的一个高性能内存分配器,旨在替代系统的默认内存分配器(如malloc、free、new、delete等)。它通过线程缓存和中央自由列表等机制,实现了高效的内存分配和回收,特别适用于多线程、高并发场景。

TCMalloc的核心优势在于其高效性和可扩展性。对于大多数对象来说,分配和释放速度非常快,且没有锁竞争。它支持两种缓存模式:每个线程缓存和每个逻辑CPU缓存,从而在不同线程数量下都能保持高效的性能。此外,TCMalloc还提供了灵活的内存使用策略,允许释放的内存重用于不同大小的对象,或返回给操作系统。

二、TCMalloc的工作原理

TCMalloc可以分为前端(Front-end)、中端(Middle-end)和后端(Back-end)三个部分。

1. 前端(Front-end)

前端是一个缓存,负责为应用程序提供快速的内存分配和释放。它有两种实现方式:每个线程缓存(per-thread cache)和每个逻辑CPU缓存(per-CPU cache)。

前端缓存中的内存以自由列表的形式存储,每个大小类别对应一个自由列表。当请求分配内存时,如果前端缓存中有适当大小的空闲对象,则直接从列表中取出并返回;如果列表为空,则从中端获取一批对象放入前端缓存。

  • 每个线程缓存:在这种模式下,每个线程都有一个独立的缓存,用于存储小对象的分配和回收。这减少了多线程环境下的锁竞争,提高了分配和释放速度。然而,随着线程数量的增加,内存占用也会相应增加。
  • 每个逻辑CPU缓存:为了解决每个线程缓存模式下内存占用高的问题,TCMalloc引入了每个逻辑CPU缓存模式。在这种模式下,系统中的每个逻辑CPU都有自己的缓存,从中分配内存。这减少了内存占用,同时保持了高效的性能。

2. 中端(Middle-end)

中端负责为前端补充缓存,并将内存归还给后端。它由传输缓存(Transfer Cache)和中央自由列表(Central Free List)组成。

  • 传输缓存:传输缓存用于在不同线程之间快速传递内存。当一个线程释放内存时,如果另一个线程正在请求相同大小的内存,则可以通过传输缓存快速满足请求。
  • 中央自由列表:中央自由列表管理着内存中的跨度(Spans),即一个或多个内存页的集合。当前端缓存中的自由列表为空时,它会从中央自由列表获取一批对象放入前端缓存。

3. 后端(Back-end)

后端负责从操作系统获取内存,并管理大对象的分配和回收。它创建多种不同尺寸的页(Pages),如4KiB、8KiB、32KiB和256KiB等,以适应不同大小的内存需求。当请求分配大对象时,后端直接从页堆中分配所需大小的页。

三、TCMalloc的使用方法

1. 安装TCMalloc

在Ubuntu/Debian系统上,可以通过以下命令安装TCMalloc:

1sudo apt update
2sudo apt install -y libgoogle-perftools-dev
3

在CentOS/Red Hat系统上,可以使用以下命令:

1sudo yum install -y gperftools gperftools-devel
2

另外,还可以通过源码编译安装TCMalloc。下载源码后,执行以下命令进行编译和安装:

1git clone https://github.com/gperftools/gperftools.git
2cd gperftools
3./autogen.sh
4./configure
5make
6sudo make install
7

2. 使用TCMalloc

TCMalloc提供了一个libtcmalloc.so动态库,加载后即可替代系统默认的内存分配器。有两种方式可以使用TCMalloc:

  • 通过LD_PRELOAD动态加载:在运行程序时,使用LD_PRELOAD环境变量加载tcmalloc:
1LD_PRELOAD=/usr/lib/libtcmalloc.so ./your_program
2
  • 在编译链接时显式指定:在程序中链接tcmalloc动态库或静态库:
1gcc -o your_program your_program.c -ltcmalloc
2

3. 调优TCMalloc

TCMalloc提供了多个环境变量来控制其行为,例如内存分配粒度、线程缓存等。常用环境变量包括:

例如,要限制线程缓存的总大小为32MB,可以执行以下命令:

1export TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES=33554432
2./your_program
3
  • TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES:限制线程缓存的总大小。
  • TCMALLOC_PAGE_SIZE:设置页的大小。

4. 调试和监控TCMalloc

TCMalloc提供了调试工具和统计信息,帮助开发者监控内存分配情况。例如,可以通过发送SIGUSR1信号给正在运行的程序,打印内存分配统计信息:

1kill -SIGUSR1 <pid>
2

此外,还可以使用TCMalloc提供的API(如MallocExtension)在程序中获取内存使用统计数据。

四、TCMalloc的应用场景和限制

TCMalloc在多线程程序中表现出更好的可扩展性和一致性,尤其是在小对象分配上。然而,随着分配对象大小的增加,性能有所下降。在32KB对象大小附近,性能有一个明显的下降,因为这是线程缓存中对象的最大尺寸。此外,TCMalloc可能不适用于未链接到libpthread.so的系统,且不会将内存返回给系统。

五、总结

TCMalloc是一个功能强大的内存分配器,通过线程缓存和中央自由列表等机制,实现了高效的内存分配和回收。它支持两种缓存模式:每个线程缓存和每个逻辑CPU缓存,适用于不同线程数量的场景。TCMalloc提供了丰富的调优选项和调试工具,帮助开发者优化内存使用并监控内存分配情况。然而,在使用TCMalloc时,也需要注意其应用场景和限制,以确保最佳的性能和兼容性。

通过本文的介绍,希望读者能够更好地理解和利用TCMalloc这一工具,提升C++应用程序的内存管理效率。

码字不易,欢迎大家点赞,关注,评论,谢谢!


推荐个C++高性能内存分配器》 是转载文章,点击查看原文


相关推荐


Redis(137)Redis的模块机制是什么?
Victor3562025/11/21

Redis 模块机制允许开发者扩展 Redis 的功能,通过编写动态加载的模块,可以向 Redis 添加新的命令、数据类型、事件处理器等。Redis 模块机制提供了一套 C 语言 API,开发者可以基于这些 API 实现自己的模块。 核心概念和数据结构 1. Redis 模块 API Redis 提供了一套模块 API,主要通过 redismodule.h 头文件定义。开发者需要包含该头文件并使用其中的函数和宏来实现模块。 2. 模块结构 每个模块需要定义一个 RedisModuleCtx 结构


C语言-----扫雷游戏
Ravi_12025/11/19

扫雷游戏的功能说明 : • 使⽤控制台实现经典的扫雷游戏 • 游戏可以通过菜单实现继续玩或者退出游戏 • 扫雷的棋盘是9*9的格⼦ • 默认随机布置10个雷 • 可以排查雷: ◦ 如果位置不是雷,就显⽰周围有⼏个雷 ◦ 如果位置是雷,就炸死游戏结束 ◦ 把除10个雷之外的所有⾮雷都找出来,排雷成功,游戏结束 test.c //⽂件中写游戏的测试逻辑 game.c //⽂件中写游戏中函数的实现等 game.h //⽂件中写游戏需要的数据类型和函数声明等 逻辑开始: 一、菜单 输入1进入游戏,输入


R语言在线编译器 | 提供快速便捷的编程环境,助力数据分析与学习
hyiciw_6422025/11/18

三十岁学编程:是挑战还是机会?|掌握编程技术,开启全新职业之路三十岁学编程,很多人可能会觉得自己已经不再适合入门这项技能。尤其在传统观念中,编程被视为年轻人的专属领域。然而,随着科技的不断发展,编程技能已经成为一种基础能力,甚至有着广阔的职业前景。对于三十岁的人来说,学习编程不仅是个人成长的一部分,更是迈向新职业的第一步。首先,三十岁的人在学习编程时,能够依靠自己丰富的生活经验与工作经历,这些都可以帮助他们更快地理解技术背后的应用场景。例如,对于在管理或市场领域工作的人来说,编程可以让他们更好地


C#.NET 全局异常到底怎么做?最完整的实战指南
唐青枫2025/11/17

简介 全局异常拦截是构建健壮企业级应用的关键基础设施,它能统一处理系统中未捕获的异常,提供友好的错误响应,同时记录完整的异常信息。 背景和作用 在 ASP.NET Core 应用中,异常可能在控制器、数据库操作或中间件中发生。如果每个动作方法都手动处理异常(如 try-catch),代码会变得冗长且难以维护。全局异常拦截器解决了以下问题: 统一错误处理:集中捕获所有未处理异常,返回标准化的错误响应。 标准化响应:符合 RESTful API 规范(如 RFC 7807 Problem D


c文件编译
芝麻馅汤圆儿2025/11/16

随笔记录 目录 1.背景 2. 编译 2.1 创建 .c 文件 2.2 编译->执行 1.背景 c文件在编译为可执行程序 2. 编译 2.1 创建 .c 文件 已知c 文件源码,创建 .c 文件并编译为可执行程序 1. creat *.c 文件 [root@localhost magx]# vim udp_nobind_sendto.c [root@localhost magx]# [root@localhost magx]# cat udp_nobind_


一句话把 Excalidraw 跑起来?SOLO Coder 把我以前踩过的坑都帮我填了
不惑_2025/11/14

Excalidraw 是一个开源、类手绘风格的虚拟白板工具,支持无限画布、暗色模式、图形库、导出 PNG/SVG、自由绘制、多语言、快捷键与绑定箭头等丰富能力。其官方应用原生支持 PWA 离线、本地优先存储、纯前端架构,非常适合私有化部署或内网使用。 要是你之前动手部署过开源项目,你应该懂那种感觉:教程看着简单,结果一动手就开始打怪,git clone → 解压 → 安装依赖 → 处理网络代理 → 启动服务 → 校验端口 → 本地预览。而这些步骤每一步都可能踩到网络、依赖、端口占用等坑。我以前搭


李飞飞「世界模型」正式开放,人人可用! Pro 版首月仅 7 元
新智元2025/11/13

「【新智元导读】只用一张图,一句话,就能创造出随便乱逛的 3D 世界——李飞飞这次不是在讲故事,而是真的给你「造梦神器」。今天起,全球上线,人人可用。」 李飞飞的「创世神器」今天终于正式上线了!人人可用。 这个由 WorldLabs 推出,名为 Marble 的网站,用世界模型可以生成瑰丽梦幻的「想象世界」~ 体验网址:marble.worldlabs.ai/ 这波属实是李飞飞自己联动自己了,前两天她的一篇万字长文火爆硅谷,定义 AI 的下一个十年是「空间智能」。 文章中,她为真正具备空间智


进入职场第四课—产出
Mapbarfront2025/11/12

新入职一家公司观察、融入、立足之后,要做的第四件事就是产出。 观察和融入帮你顺利度过新手期,立足则让你在团队中站稳脚跟,被大家真正接受,接下来你要做的是保持稳定,持续不断的产出,让团队感受到你究竟有多大能量。 易经乾卦中的终日乾乾,说的就是这个意思,终日指的是持续不断,意味着不能三天打鱼两天晒网,有了开头没有结尾,乾乾代表着产出,要有价值、有思考、有进阶,不能只做重复工作,毕竟在易经中,乾代表天,想完成立足到产出的关键跃升,以下这4个动作一定要做好。 1、产出有价值的成果。 立足期是你独立承担任


SpringBoot实现隐式参数注入
风象南2025/11/10

前言:一个痛点 想象一下这样的场景:用户请求带着 JWT Token 进入你的系统,Filter 层面解析 Token 得到用户 ID,接下来需要: 在 Controller 层获取用户信息 在 Service 层进行权限验证 在某些业务逻辑中记录操作日志 每一个环节都需要知道"当前用户是谁",看看目前常用的解决方案。 传统方案的"缺陷" 方案一:ThreadLocal // 看起来很"Hack" private static final ThreadLocal<Long> currentU


Python实战:用高德地图API批量获取地址所属街道并写回Excel
程序员爱钓鱼2025/11/8

在日常的数据处理工作中,我们经常需要根据公司、事件或门店的注册地址,批量获取其所在的街道信息,例如“浦东新区张江镇”“徐汇区龙华街道”等。 手动查询显然低效,而借助 Python + 高德地图API,我们可以轻松实现自动化批量查询并将结果写入 Excel 文件中。 本文将完整展示一个从 Excel 读取地址 → 调用高德API → 获取街道 → 写回Excel的实用脚本,并讲解实现细节与优化思路。 一、功能概述 这段脚本的功能可以总结为四步: 从 Excel 文件中读取地址数据; 调用高德

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2025 聚合阅读