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

news/2025/10/10 9:10:17/文章来源:https://www.cnblogs.com/ljbguanli/p/19132358

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.mzph.cn/news/933979.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

完整教程:考研408计算机网络第47题(2024年)

完整教程:考研408计算机网络第47题(2024年)pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &q…

进步与现代化

线性方程组 线性无关、系数矩阵行列式、解的情况 简化行阶梯型矩阵:主元全 \(1\),所在行左侧全 \(0\),所在列剩余全 \(0\) 生成子空间:\(\langle A\rangle\),线性表出の所有向量 \(A\) 线性无关 \(\Longleftright…

2025 最新推荐!溴化锂回收公司精选榜单:含制冷机 / 溶液 / 机组回收服务商权威测评及选择指南

随着工业与商业领域溴化锂制冷设备迭代加速,老旧设备处置需求激增,但市场仍存在服务标准混乱、环保措施缺失、技术能力参差不齐等痛点。部分机构拆解流程不规范,既造成铜、铝等资源浪费,又易因溴化锂溶液泄漏引发污…

使用OpenCvSharp , Emgu.CV 手搓 视觉识别算法 以及 成果展示

举个🌰 一个培养皿里有若干条鱼苗,需要将它全部区分识别出来, 像如下图所示的小蝌蚪就是(培养皿里三个黑点是热带鱼苗,做实验用的,一毫米长) 用的是海康威视的黑白工业相机拍摄。 先讲讲思路,图片是一组庞大的…

PKC7300高频电流探头在新能源汽车车载充电机稳态电流测试中的应用方案

一、应用背景 新能源汽车车载充电机(OBC)是将外部电网电能转换为车载动力电池电能的关键部件。在工作过程中,它需要处理0-300A的电流,而其内部的高频开关电路容易产生干扰信号。因此,对电流测量的量程、高频信号捕…

质量检验知识专题讲座之六:抽样检验步骤

抽样检验步骤抽样检验是从一批产品中随机抽取部分样本进行检验,再根据样本结果判断整批产品是否合格的过程,主要步骤如下: 1)、确定抽样检验的对象和目的 明确需要检验的产品批次、检验的质量特性(如尺寸、性能、…

羡慕线段树

顺颂 YFST 板子 & 使用例 题。首先树剖,然后变成在 \(\text{dfn}\) 区间上插一个关于 \(\text{dis}\) 的一次函数。这个很神奇,一般的李超树是,在 \(x\) 轴区间上插入关于 \(x\) 的一次函数。然而这里,\(\text…

质量检验知识专题讲座之七:来料检验

来料检验(IQC)1、来料检验的定义: 来料检验是指对采购进来的原材料、部件或产品做品质确认和查核,即在供应商送原材料或部件时通过抽样的方式对品质进行检验,并最后做出判断该批产品是允收还是拒收。 来料检验是企业…

windows 10分区教程,win10自带分区教程

win10怎么分区?win10自带磁盘分区,有几个人会?win10磁盘分区 不需要任何软件,win10系统本身就有这个功能,下面开始操作 第一步 按快捷键【wins+X】的组合键,在弹出的选项中选择【磁盘管理】选项;如下图: ​​ …

巴斯勒相机:30 年工艺沉淀,重新定义机器视觉效率​

巴斯勒相机:30 年工艺沉淀,重新定义机器视觉效率​2025-10-10 08:43 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; dis…

决斗(模拟赛题目T3)分析

感觉很典,所以就记下来了。我们考虑一个非常重要的事实: - 田忌赛马对于每一个 $a_i$ 找的是第一个比他大的 $b_i$。 - 而字典序最大又需要前面的尽可能大。这似乎产生了矛盾,让这道题目看起来有点难。我们考虑不用…

Guidde:AI驱动的视频文档创建工具 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

大学C语言课摸鱼记

2025.10.10 终于开启了大学的第一节C语言课。不得不说,C语言课当早八是真抽象。 什么叫C语言理论课不在机房???什么叫开学第十周才上机学习??? C语言教材第三章才教 scanf 和 printf ,😓 太抽象了。

2025.10.10——1绿

普及+/提高- P1503 鬼子进村 原以为线段树维护最后的1,后来发现可以用二分+树状数组log(n)^2解决

gitlen中,已经提交了内容,如何回退到修改前?

在 Git 中,如果已经提交了内容并想要回退到修改前的状态,可以根据具体需求使用以下几种方法: 1. 撤销最近一次提交(保留修改内容) 如果你想撤销最近的提交,但保留工作区的修改(以便重新修改后再次提交),可以使…

HCIP-IoT/H52-111 真题详解(章节C),接入实用的技术和网络设计 /Part1

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

CF1989F

思路 简单有趣的一道题。 发现操作一次不会使得 \(y=-x+b\) 和 \(x=k\) 这两条直线上的奇偶性发生改变。 两条不平行直线确定一个交点,可以直接找出原始的点。

基于UML/MARTE的汽车安全关键系统设计手段

基于UML/MARTE的汽车安全关键系统设计手段2025-10-10 08:08 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: bloc…

MySQL 8.0 my.cnf 配置详解

MySQL 8.0 my.cnf 配置详解MySQL 配置文件(通常命名为 my.cnf 或 my.ini)是控制数据库运行行为的核心载体,尤其在 MySQL 8.0 版本中,诸多参数默认值与旧版差异显著(如默认字符集、认证插件、InnoDB 特性)。合理配…

Vue3水波纹指令:2025年Material Design交互新标准 - 实践

Vue3水波纹指令:2025年Material Design交互新标准 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consola…