当前位置: 首页 > news >正文

RapidJSON 自定义内存分配器详解与实战 - 详解

RapidJSON 自定义内存分配器详解与实战 - 详解

前言

RapidJSON 是一个高性能的 C++ JSON 解析/生成库,其默认使用 MallocAllocator —— 即直接调用 malloc/free 进行内存分配。在大多数场景下这完全够用。
但在高性能、低延迟、高并发或嵌入式环境中,频繁调用系统级 malloc/free 会带来:内存碎片化、分配/释放性能瓶颈、缓存不友好等问题
RapidJSON 从设计之初就支持 Allocator 模板参数,允许你“插拔”任意符合接口的内存管理器,真正做到“零成本抽象”。

一、标题rapidjson源码分析

#define RAPIDJSON_DEFAULT_ALLOCATOR ::RAPIDJSON_NAMESPACE::MemoryPoolAllocator<
::RAPIDJSON_NAMESPACE::CrtAllocator>
//...省略
template <
typename Encoding, typename Allocator = RAPIDJSON_DEFAULT_ALLOCATOR >
class GenericValue
{
public:
//! Name-value pair in an object.
typedef GenericMember<Encoding, Allocator> Member;typedef Encoding EncodingType;//!< Encoding type from template parameter.typedef Allocator AllocatorType;//!< Allocator type from template parameter.typedef typename Encoding::Ch Ch;//!< Character type derived from Encoding.typedef GenericStringRef<Ch> StringRefType;//!< Reference to a constant stringtypedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator;//!< Member iterator for iterating in object.typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator;//!< Constant member iterator for iterating in object.typedef GenericValue* ValueIterator;//!< Value iterator for iterating in array.typedef const GenericValue* ConstValueIterator;//!< Constant value iterator for iterating in array.typedef GenericValue<Encoding, Allocator> ValueType;//!< Value type of itself.typedef GenericArray<false, ValueType> Array;typedef GenericArray<true, ValueType> ConstArray;typedef GenericObject<false, ValueType> Object;typedef GenericObject<true, ValueType> ConstObject;///...省略

通过rapidjson::GenericValue代码分析得出,GenericValue 是可以使用自定义的Allocator 分配器的,其默认为RAPIDJSON_DEFAULT_ALLOCATOR ,而这个宏又指向名为CrtAllocator的类

#ifndef RAPIDJSON_MALLOC
///! customization point for global \c malloc
#define RAPIDJSON_MALLOC(size) std::malloc(size)
#endif
#ifndef RAPIDJSON_REALLOC
///! customization point for global \c realloc
#define RAPIDJSON_REALLOC(ptr, new_size) std::realloc(ptr, new_size)
#endif
#ifndef RAPIDJSON_FREE
///! customization point for global \c free
#define RAPIDJSON_FREE(ptr) std::free(ptr)
#endif
//..........省略
//! C-runtime library allocator.
/*! This class is just wrapper for standard C library memory routines.
\note implements Allocator concept
*/
class CrtAllocator
{
public:
static const bool kNeedFree = true;
void* Malloc(size_t size) {
if (size) // behavior of malloc(0) is implementation defined.
return RAPIDJSON_MALLOC(size);
else
return NULL;
// standardize to returning NULL.
}
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
(void)originalSize;
if (newSize == 0) {
RAPIDJSON_FREE(originalPtr);
return NULL;
}
return RAPIDJSON_REALLOC(originalPtr, newSize);
}
static void Free(void *ptr) RAPIDJSON_NOEXCEPT {
RAPIDJSON_FREE(ptr);
}
bool operator==(const CrtAllocator&
) const RAPIDJSON_NOEXCEPT {
return true;
}
bool operator!=(const CrtAllocator&
) const RAPIDJSON_NOEXCEPT {
return false;
}
};

CrtAllocator类为C++申请内存的默认方式(malloc、realloc、free)
由此得出结论,仅需要自定义实现一个CrtAllocator类似的类,即可自定义rapidjson的内存分配器

class MyAllocator
{
public:
static const bool kNeedFree = true;
// 是否需要显式释放内存
void* Malloc(size_t size);
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);
void Free(void* ptr);
};

二、应用举例

1.以提高内存使用效率、减少碎片为目的

通过我的另外一篇文章QT基于mmap文件映射机制实现的内存池方法总结,实现自定义内存申请方式,即可将json数据映射到磁盘或其他储存中,减少内存的占用

2.性能分析、内存泄漏检测等场景

class CrtAllocatorWithStats
{
public:
static const bool kNeedFree = true;
size_t totalAllocated = 0;
size_t totalFreed = 0;
size_t peakUsage = 0;
void* Malloc(size_t size) {
void* ptr = std::malloc(size);
if (ptr) {
totalAllocated += size;
peakUsage = std::max(peakUsage, totalAllocated - totalFreed);
}
return ptr;
}
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
void* ptr = std::realloc(originalPtr, newSize);
if (ptr) {
if (newSize > originalSize) {
totalAllocated += (newSize - originalSize);
} else {
totalFreed += (originalSize - newSize);
}
peakUsage = std::max(peakUsage, totalAllocated - totalFreed);
}
return ptr;
}
void Free(void* ptr) {
if (ptr) {
// 注意:无法知道释放了多少字节,除非记录分配表(略复杂)
// 此处简化处理
totalFreed += 1;
// 仅计数次数
}
std::free(ptr);
}
};

通过重写Allocator并在内存释放、申请等位置计数或计时,就能对此性能进行分析

三、总结

自定义内存分配器是 RapidJSON 高性能的“隐藏武器”,它让你在内存控制、性能优化、场景适配上拥有极大的自由度。虽然大多数项目用默认分配器就够了,但在游戏、高频交易、嵌入式、服务端网关等场景,一个精心设计的 Allocator 能带来数倍性能提升和更低的延迟波动。
欢迎点赞、收藏、转发!

http://www.zskr.cn/news/17985.html

相关文章:

  • 进步与现代化
  • 使用OpenCvSharp , Emgu.CV 手搓 视觉识别算法 以及 成果展示
  • 巴斯勒相机:30 年工艺沉淀,重新定义机器视觉效率​
  • Guidde:AI驱动的视频文档创建工具 - 详解
  • 大学C语言课摸鱼记
  • CCPC2024女生专场 游记(VP)
  • 华为 AP hw_manage 离线管理 Wi-Fi 密码
  • STM32 教程
  • LCR 129. 字母迷宫
  • 日志|电话号码的字母组合|子集|回溯
  • 【题解】P12992 [GCJ 2022 #1C] Intranets
  • ysyx:pa3.1批处理系统
  • JAVA: Mybatis添加xml执行多行更新语句时报错
  • 065_尚硅谷_赋值运算符基本使用
  • 20232416 2025-2026-1《网络与系统攻防技术》实验一实验报告
  • 1.1.1.1 金融市场的定义与功能
  • 每日反思
  • 1.1.1.2 直接融资vs间接融资的区别
  • 柳高国庆小小说创作比赛的构思和成文(未完成)
  • 被彼此笼罩 任歌声将我们缠绕 立下誓言后再自嘲 重复仲夏夜的舞蹈 吞下这毒药
  • 朝圣显像 不及那人将门扉轻轻叩响 欢迎来到我的城市 嗅玫瑰绽放
  • 分布式锁的 Java 实现与性能对比:从实战落地到选型指南(一) - 指南
  • 2025.10.9 月考游寄 - Amy
  • 七层协议
  • 10.9正式恢复
  • 2025.10.8 训练记录
  • 【触想智能】工业一体机在金融领域的应用优势和具体注意事项 - 指南
  • 【每日一面】盒子模型
  • ai 对话框一直往下滚可能要成为过云,当初只是为了快速现实ai的演示界面而己,是该走入正题 了
  • 脚手架安全巡检智能化!AI 让隐患识别更精准、整改更高效