OceanBase内存管理小窍门
本文来自OceanBase热心用户的实践分享。
本文主要是对OceanBase内存管理的实用技巧分享,而并非直接深入OceanBase的代码层面进行阐述。
阅读本文章你将了解:
- 重载运算符new 与malloc在返回值上区别?
- 在ceph 双向链表新用法,一个类定义时候 成员变量就是包含了 双向链表节点,可以通过该节点反推 类其他变量吗?
- 在stl中 中如何利用单链表存储申请批量对象?从对象中拿出固定字节就就可充当单链表?
- ob ob_allocator.h 与stl ob_allocator.h 分配器实现 有什么差别?
内存管理
C++中通过new和delete两个关键字进行动态内存管理。 c语言通过 malloc 和free 两个关键字进行动态内存管理
函数支持重载,运算符同样也支持重载
C++的提供了 重载运算符这一特性, 本质也是operators()函数重载,当遇到该运算符时就调用函数一样。
运算符重载的限制
小提示:Markdown左对,在原来基础上,后面一个空格就解决了 右对齐HTML css语法
重载运算符new
throwing (1) void* operator new (std::size_t size);
// throwing allocation ,On failure, it throws a bad_alloc exceptionnothrow (2) void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) noexcept;
//nothrow allocation on failure it returns a null pointer instead of throwing an exceptionplacement (3) void* operator new (std::size_t size, void* ptr) noexcept;
//placement Simply returns ptr (no storage is allocated).
// A pointer to an already-allocated memory block
代码示例
MyClass * p1 = new MyClass();
// allocates memory by calling: operator new (sizeof(MyClass))
// and then constructs an object at the newly allocated spacestd::cout << "2: ";MyClass * p2 = new (std::nothrow) MyClass();
// allocates memory by calling: operator new (sizeof(MyClass),std::nothrow)
// and then constructs an object at the newly allocated spacestd::cout << "3: ";
new (p2) MyClass();//p2
delete p1;
delete p2;
malloc
https://en.cppreference.com/w/c/memory/malloc
void *malloc( size_t size );
Allocates size bytes of uninitialized storage,
alloc is thread-safeParameters
size - number of bytes to allocate
sizeof Queries size of the object or type.On failure, returns a null pointer.
ob代码:ob_alter_table_resolver.cpp
//申请批量内存时候使用,__MemoryContext__ *tmp = new (std::nothrow) __MemoryContext__();abort_unless(tmp != nullptr); //void *tmp_ptr = NULL;common::ObIAllocator *allocator_;//分配器if (NULL == (tmp_ptr = (ObAlterPrimaryArg *)allocator_->alloc(sizeof(obrpc::ObAlterPrimaryArg)))) {} else {alter_pk_arg = new (tmp_ptr) ObAlterPrimaryArg(); //这里没有使用delete}
重载new运算符 使用场景
- 批量申请内容时候,使用std::nothrow 不抛出异常,通过返回值判断nullptr 来处理
- C++ placement new与内存池有关系,能帮助更节省内存吗?不清楚继续看
有些时候我们需要能够长时间运行的程序(例如监听程序,服务器程序)对于这些7*24运行的程序,我们不应该使用标准库提供的new 和 delete (malloc和free也算)。这是因为随着程序的运行,内存不断的被申请和被释放,频繁的申请和释放将会引发内存碎片、内存不足等问题,影响程序的正常运行。
更多的时候核心程序不允许内存申请失败,更不允许异常的出现,因此必须保证每次内存申请都是成功的(一般都是内核程序,当然不希望被中断的后台程序也是如此)。在这种极端要求下,内存池的好处就大大的凸现出来了。
在C++中,可以通过placement new 来实现内存池
如果分配能节省内存
内存池是很大概念,我平时用不到,上来不会说明原理,这是自己给自己挖坑,自己不会还要去自己讲清楚 先看一段代码,你发现什么错误吗?
一般定义链表,都有T 成员表示,但是ceph 中 定义 elist为什么没有,它怎么存储数据呢?
class Node
{
public:int data; //存储数据Node * last;Node * next;};class DoubleNode
{
private:Node * head; //头结点Node * tail; //尾节点
};
一般定义链表,都有T 成员表示,但是elist为什么没有,它怎么存储数据呢?
完整代码:
https://lab.forgefriends.org/ceph/ceph/-/blob/wip-rgw-placement-rule-empty/src/include/elist.h
/** elist: embedded list. 这是一个双向链表,必须和类耦合起来。* elist(embedded list)是一种特殊类型的链表,它允许将链表节点直接嵌入到用户定义的数据结构中。这种设计使得每个数据项可以作为链表的一部分* requirements:* - elist<T>::item be embedded in the parent class 定义类时候,必须使用 elist<T>::item 当作一个成员* - items are _always_ added to the list via the same elist<T>::item at the same* fixed offset in the class. //items 在类中偏移量* - begin(), front(), back() methods take the member offset as an argument for traversal.**///计算成员变量在类中的偏移量
#define member_offset(cls, member) ((size_t)(&((cls*)1)->member) - 1)template<typename T>
class elist {
public:struct item {item *_prev, *_next;//通过偏移量T get_item(size_t offset) {ceph_assert(offset);return (T)(((char *)this) - offset); }}; //elist<T>::item 是作为用户定义结构体的成员变量存在的。//意味着 item 的内存是从用户结构体的内存中分配的,而不是独立分配。private:item _head;size_t item_offset;
}class iterator {private:item *head;item *cur, *next;size_t item_offset;public:T operator*() {return cur->get_item(item_offset);}
};
- c++ 内存模型 (了解)
GCC 或 Clang,你可以使用 __builtin_offsetof
函数来获取成员的偏移量:
#define member_offset(cls, member) ((size_t)(&((cls*)1)->member) - 1)
class Example {
public:char a; // 1 byteint b; // 4 bytes, aligned to 4 bytesdouble c; // 8 bytes, aligned to 8 bytesbool d; // 1 byte, but often padded to align with 'b'
};size_t offset_a = __builtin_offsetof(Example, a);__size_t offset_b = __builtin_offsetof(Example, b)能否提供一个完整的示例,展示如何在一个复杂的类中嵌入 `elist` 并使用它?https://kimi.moonshot.cn/share/cqqc6ga1n4gqsenn4ur0
https://kimi.moonshot.cn/share/cqqcdsdskq8g1pv5ces0
STL源码剖析 by 侯捷 提到一个同样技巧
资料:STL标准库与泛型编程
- what:关于STL中空间配置器中free_list的理解,理解不了_Obj 单链表将多个 对象组织起来?
union _Obj {union _Obj* _M_free_list_link; // 单链表char _M_client_data[1]; /* The client sees this. */}; 关于STL中空间配置器中free_list的理解
- how:参考资料
自己动手实现STL 01:内存配置器的实现(stl_alloc.h)
https://github.com/wangcy6/sgi-stl/blob/master/stl_alloc.h
https://www.cnblogs.com/wangjzh/p/4097355.htmlhttps://github.com/wangcy6/STLSourceCodeNote
第一级配置器malloc_alloc 就是,直接调用系统的malloc分配内存
//第一级配置器malloc_alloc 就是,直接调用系统的malloc分配内存
typedef __malloc_alloc_template<0> malloc_alloc;template <int __inst> //这个模板没啥意义,区分一级二级区别
class __malloc_alloc_template {
private:static void* _S_oom_malloc(size_t);static void* _S_oom_realloc(void*, size_t);
public:static void* allocate(size_t __n){void* __result = malloc(__n);if (0 == __result) //malloc是否返回0__result = _S_oom_malloc(__n); //分配失败继续分配return __result;}static void deallocate(void* __p, size_t /* __n */){free(__p);}
}
第二级配置器(Second-level allocator):。
default_alloc 尝试通过分配大块内存(称为 "chunks")来减少内存碎片,并使用这些大块内存来满足较小的内存请求。 它使用一个自由列表(free list)机制来管理这些大块内存中的小块内存。
default_alloc 可以是线程安全的,并且提供了更好的内存局部性和缓存性能。
//第二级配置器typedef __default_alloc_template<__NODE_ALLOCATOR_THREADS, 0> alloc;
template <bool threads, int inst>
class __default_alloc_template {union _Obj {union _Obj* _M_free_list_link;char _M_client_data[1]; /* The client sees this. */};
}_S_refill(size_t __n)
{// 定义分配的对象数量为20,这个值可以根据需要调整。int __nobjs = 20;// 调用 _S_chunk_alloc 函数分配足够存储 __nobjs 个大小为 __n 的对象的内存块。char* __chunk = _S_chunk_alloc(__n, __nobjs);// __my_free_list 指向适当大小的自由列表的指针。_Obj* __STL_VOLATILE* __my_free_list;// __result 指向新分配的内存块的起始位置,将被返回给调用者。_Obj* __result;// __current_obj 和 __next_obj 用于遍历和设置对象链表的指针。_Obj* __current_obj;_Obj* __next_obj;// __i 是循环计数器。int __i;// 如果只分配了一个对象,就直接返回这个对象的内存。if (1 == __nobjs) return(__chunk);// 计算并获取对应大小的自由列表。__my_free_list = _S_free_list + _S_freelist_index(__n);// 构建内存块内的自由链表。// __result 初始化为指向内存块的起始位置。__result = (_Obj*)__chunk;// 第一个对象之后的对象地址设置为自由链表的头。*__my_free_list = __next_obj = (_Obj*)(__chunk + __n);// 循环将内存块分割成多个对象,并用 _M_free_list_link 将它们链接起来。for (__i = 1; ; __i++) {// __current_obj 指向当前正在处理的对象。__current_obj = __next_obj;// 计算下一个对象的地址。__next_obj = (_Obj*)((char*)__next_obj + __n);// 如果这是分配的最后一个对象,将其 _M_free_list_link 设置为 NULL,结束链表。if (__nobjs - 1 == __i) {__current_obj -> _M_free_list_link = 0;break;} else {// 否则,将当前对象的 _M_free_list_link 设置为指向下一个对象。__current_obj -> _M_free_list_link = __next_obj;}}// 返回可以立即使用的首个对象的地址。return(__result);
}
OceanBase怎么做的
- 先看例子
ParseNode *key_child_node;key_child_node = static_cast<ParseNode*>(allocator.alloc(sizeof(ParseNode))) //key_child_node = new(key_child_node) ParseNode;oceanbase/deps/oblib/src/lib/allocator/ob_allocator.hclass ObAllocator : public ObIAllocator//直接看看发狂,概念太多,还是stl看着舒服//
- 参考:从0到1 OceanBase原生分布式数据库内核实战进阶版
从0到1 OceanBase原生分布式数据库内核实战进阶版
相关文章:
OceanBase内存管理小窍门
本文来自OceanBase热心用户的实践分享。 本文主要是对OceanBase内存管理的实用技巧分享,而并非直接深入OceanBase的代码层面进行阐述。 阅读本文章你将了解: 重载运算符new 与malloc在返回值上区别?在ceph 双向链表新用法&am…...
【问题解决】git status中文文件名乱码
问题复现 解决办法 在git bash中直接执行如下命令 git config --global core.quotepath false原因 通过 git config --help 可以查看到以下内容: core.quotePath Commands that output paths (e.g. ls-files, diff), will quote “unusual” characters in the p…...
探索数据结构:AVL树的分析与实现
✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:数据结构与算法 贝蒂的主页:Betty’s blog 1. AVL树的介绍 在前面我们学习二叉搜索树时知道,在数据有序…...
使用 C++ 实现简单的插件系统
使用 C 实现简单的插件系统 在现代软件开发中,插件系统是一种常见的架构模式,它允许开发者在不修改主程序的情况下,扩展应用程序的功能。通过插件,用户可以根据需要添加或移除功能模块,从而提高软件的灵活性和可维护性…...
使用Python创建省份城市地图选择器
在这篇博客中,我们将探讨如何使用Python创建一个简单而实用的省份城市地图选择器。这个项目不仅能帮助我们学习Python的基础知识,还能让我们了解如何处理JSON数据和集成网页浏览器到桌面应用程序中。 C:\pythoncode\new\geographicgooglemap.py 全部代码…...
【Java 数据结构】Stack和Queue介绍
Stack和Queue StackStack是什么Stack的使用构造方法常用方法 栈的模拟实现初始化和基本方法入栈出栈查看栈顶 栈的应用链栈的简单介绍 QueueQueue是什么Queue的使用队列的模拟实现初始化入队出队查看队头元素 循环队列循环队列的定义及其注意点循环队列的实现初始化和基本方法获…...
Docker基本语法
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、更新yum镜像仓库(一)查看本地yum镜像源地址(二)设置docker的镜像仓库(1)安装必要工具…...
uniapp 对于scroll-view滑动和页面滑动的联动处理
需求 遇到一个需求 解决方案 这个时候可以做一个内页面滑动判断 <!-- scroll-y 做true或者false的判断是否滑动 --> <view class"u-menu-wrap" style"background-color: #fff;"><scroll-view :scroll-y"data.isGo" scroll-wit…...
opencv基础的图像操作
1.读取图像,显示图像,保存图像 #图像读取、显示与保存 import numpy as np import cv2 imgcv2.imread(./src/1.jpg) #读取 cv2.imshow("img",img) #显示 cv2.imwrite("./src/2.jpg",img) #保存 cv2.waitKey(0) #让程序进入主循环(让…...
Java | Leetcode Java题解之第337题打家劫舍III
题目: 题解: class Solution {public int rob(TreeNode root) {int[] rootStatus dfs(root);return Math.max(rootStatus[0], rootStatus[1]);}public int[] dfs(TreeNode node) {if (node null) {return new int[]{0, 0};}int[] l dfs(node.left);i…...
本地查看的Git远程仓库分支与远程仓库分支数量不一致
说明:一次,在IDEA中想切换到某分支,但是查看Remote没有找到要切换的分支,但是打开GitLab,查看远程仓库,是有这个分支的。 解决:1)在IDEA的Git中,点下面Fatch获取一下远程…...
opencv-python实战项目九:基于拉普拉斯金字塔的图像融合
文章目录 一,简介:二,拉普拉斯金字塔介绍:三,算法实现步骤3.1 构建融合拉普拉斯金字塔3.2 融合后的拉普拉斯金字塔复原: 四,整体代码实现:五,效果: 一&#x…...
浅谈JDK
JDK(Java Development Kit) JDK是Java开发工具包,是Java编程语言的核心软件开发工具。 JDK包含了一系列用于开发、编译和运行Java应用程序的工具和资源。其中包括: 1.Java编译器(javac):用于将Java源代码编译成字节…...
爬虫案例3——爬取彩票双色球数据
简介:个人学习分享,如有错误,欢迎批评指正 任务:从500彩票网中爬取双色球数据 目标网页地址:https://datachart.500.com/ssq/ 一、思路和过程 目标网页具体内容如下: 我们的任务是将上图中…...
C++ | Leetcode C++题解之第337题打家劫舍III
题目: 题解: struct SubtreeStatus {int selected;int notSelected; };class Solution { public:SubtreeStatus dfs(TreeNode* node) {if (!node) {return {0, 0};}auto l dfs(node->left);auto r dfs(node->right);int selected node->val…...
软件架构设计师-UML知识导图
软件架构设计师-UML知识导图,包含如下内容: 结构化设计,包含结构化设计的概念、结构化设计的主要内容、概要设计、详细设计及模块设计原则;UML是什么:介绍UML是什么;UML的结构:构造块、公共机制…...
在使用transformers和pytorch时出现的版本冲突的问题
在使用transformers和torch库的时候,出现了以下问题: 1、OSError: [WinError 126] 找不到指定的模块。 Error loading "D:\Program Files\anaconda3\envs\testenv\Lib\site-packages\torch\lib\fbgemm.dll" or one of its dependencies. 2、…...
uniapp粘贴板地址识别
1: 插件安装 主要是依靠 address-parse 这个插件: 官网 收货地址自动识别 支持pc、h5、微信小程序 - DCloud 插件市场 // 首先需要引入插件 npm install address-parse --save 2:html部分 <view class""><view class&quo…...
C语言 | Leetcode C语言题解之第335题路径交叉
题目: 题解: bool isSelfCrossing(int* distance, int distanceSize){if (distance NULL || distanceSize < 4) {return false;}for (int i 3; i < distanceSize; i) {if ((distance[i] > distance[i - 2]) && (distance[i - 1] &l…...
TypeScript学习第十三篇 - 泛型
在编译期间不确定变量的类型,在调用时,由开发者指定具体的类型。 1. 如何给arg参数和函数指定类型? function identity(arg){return arg; }identity(1) identity(jack) identity(true) identity([]) identity(null)定义的时候,无…...
工业智能网关在汽车制造企业的应用价值及功能-天拓四方
随着工业互联网的飞速发展,工业智能网关作为连接物理世界与数字世界的桥梁,正逐渐成为制造业数字化转型的核心组件。本文将以一家汽车制造企业的实际使用案例为蓝本,深入解析工业智能网关在实际应用中的价值、功能及其实操性。 一、背景与挑…...
LLM - 在服务器中使用 Ollama + OpenWebUI 部署最新大模型
欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/140992533 免责声明:本文来源于个人知识与公开资料,仅用于学术交流,欢迎讨论,不支持转载。 Ollama 是一个开源的大型语言模型(LLM)服务工具,目的是简化本地运行…...
重启人生计划-积蓄星火
🥳🥳🥳 茫茫人海千千万万,感谢这一刻你看到了我的文章,感谢观赏,大家好呀,我是最爱吃鱼罐头,大家可以叫鱼罐头呦~🥳🥳🥳 如果你觉得这个【重启人生…...
2024.08.11 校招 实习 内推 面经
地/球🌍 : neituijunsir 交* 流*裙 ,内推/实习/校招汇总表格 1、自动驾驶一周资讯 - 比亚迪将采购华为智驾系统,用于方程豹新款越野车;英特尔发布第一代车载独立显卡;黑芝麻智能上市首日破发大跌 自动…...
LCA(Lowest Common Ancestor)
LCA(Lowest Common Ancestor) 定义 在树上取两点 x,yx,y,他们的 LCA 为距离他们最近的公共祖先。 本章主要讲的是倍增求 LCA。 暴力求取 从 xx 开始向上移动到根结点,并标记沿途结点。从 yy 开始向上移动到根结点,…...
张钹院士:大模型时代的企业AI发展趋势
在当今技术迅速发展的时代,生成式人工智能与大模型正成为推动产业变革的重要力量。随着AI技术的不断成熟与普及,它的应用已从个人领域扩展至企业层面,广泛覆盖各行各业。 那么,新技术究竟会给产业带来哪些积极地影响?…...
php连接sphinx的长连接事宜以及sphinx的排除查询以及关于sphinx里使用SetSelect进行复杂的条件过滤或复杂查询
一、php连接sphinx的长连接事宜以及sphinx的排除查询 在使用php连接sphinx时,默认的sphinx连接非长连接,于是在想php连接sphinx能否进行一些优化 publish:January 9, 2018 -Tuesday: 方法:public bool SphinxClient::open ( void ) — 建立到…...
抓包分析排查利器TCPdump
tcpdump命令介绍与常规用法。 基础命令介绍 # 固定语法 -i 指定网卡名称 -nn 显示IP地址 -w 指定输出的文件名称 tcpdump -i eth0 -nn -w test.cap-nn 不把主机的网络地址与协议转换成名字 -w 把数据包数据写入指定的文件 and 连接参数 host 指明主机 port 指明端口 src 源IP…...
八种排序算法的复杂度(C语言)
归并排序(递归与非递归实现,C语言)-CSDN博客 快速排序(三种方法,非递归快排,C语言)-CSDN博客 堆排序(C语言)-CSDN博客 选择排序(C语言)以及选择排序优化-CSDN博客 冒泡排序(C语言)-CSDN博客 直接插入排序(C语言)-CSDN博客 希尔排序( 缩小增量排序 )(C语言)-CSDN博客 计数…...
docker compose部署rabbitmq集群,并使用haproxy负载均衡
一、创建rabbitmq的data目录 mkdir data mkdir data/rabbit1 mkdir data/rabbit2 mkdir data/rabbit3 二、创建.erlang.cookie文件(集群cookie用) echo "secretcookie" > .erlang.cookie 三、创建haproxy.cfg配置文件 global log stdout fo…...
网站反向绑定域名/如何优化关键词
在 multi-voltage design 中,常常用到isolation cell,本文简单介绍什么是 iso cell, 何时需要加 iso cell,以及如何使用 iso cell 1. 什么是 iso cell ? isolation cell 一般用于隔离两个不同的 power domain …...
安卓开发app/贵港网站seo
...
table做网站/网站推广优化方案
在filter中经常会遇到>begindate这样的例子 而最终导致和日期提示控件之间相互比较的时候报错,日期格式类错误 于是做了如下的操作,再次用新的参数添加过滤器,一切正常。神奇的mysql. 第一步: cast([日期],varchar(8)) 第二步&…...
域名注册商网站/seo 优化 工具
1. 完成之前系列文章涉及内容后,继续在命名提示符下运行rendom /prepare,此步骤主要是校验DC是否全部准备完成,如下图所示;2. 如果上述步骤中出现失误,比如发现新域名书写错误等,可以运行rendom /end&#…...
成都装修公司网站建设/我的百度购物订单
前言近一周学习了CSS的用法,在此对一周所学进行总结。语法常用的CSS语法大致可分为四种,:选择器{属性名: 属性值 /*注释*/},如div{background: red;}2. charset,用于设置样式表中的字符编码,必须放在第一行,…...
wordpress大前端破解/宁波seo网络推广推荐
Part 2 动画 我们通过set方法就可以快速的修改canvas上的图形的属性。但是,往往我们在开发网站的时候除了完成功能需求之外,也需要提高网页的美观。所以动画是一个必不可少的功能。 举个例子: rect.set(angle, 45);给这个变化属性添加动画…...