C/C++内存管理器
C标准库提供了malloc,free,calloc,realloc,C++标准库还提供了new, new[], delete, delete[]。这些用来管理内存,看起来够用了,为啥还要自己写一个内存管理器呢?
原因还是从性能考虑:例如malloc和new是出于通用性考虑的,能处理多线程情况(multithread)。对于单线程的程序,这种额外的功能反而降低性能。
而且还注意到,new/delete/free/malloc都是要在user-space和kernel-code做切换的,context的切换会降低性能。如果自己写一个user-land的内存管理器,就能大幅减少这种切换。还有就是GC(garbage collection)。
几点要求
- 速度:比编译器的内存分配器要快才行
- 鲁棒:不能有内存泄漏,分配多少就收回多少
- 方便:用户不怎么需要改代码,就能把内存管理器加进去
- 移植:应当跨平台,用户在啥系统上都能用,方便移植
前人经验
- 申请大块内存
一次性申请一大块内存,减少向系统申请的次数,以后需要申请内存就从这一大块上分配。
(这不就是缓存么。。) - 为特定尺寸优化
任何程序中都一种最常见的内存申请尺寸。为这种尺寸优化,提升性能。 - 需要删除的内存暂时存放在容器中(敝帚自珍)
从用户角度看,变量声明周期结束,要释放分配的内存;但是内存管理器实际上可以“不真的把这块内存还给系统”,而是攒起来留给后续需要分配内存时用。当然,这种内存更多的是碎片,所以再分配时可能不够用,那就得再找大块内存去分配了。
代码,版本1
首先是一个不使用内存管理器的代码,内存的申请和释放是手动完成的,并且放在for循环中,来频繁的申请和释放,方法这种做法的效果(慢啊)。代码:
#include <ctime>
#include <iostream>
using namespace std;
class Complex
{
public:
Complex(double a, double b) : r(a),c(b)
{
}
private:
double r; //实部
double c; //虚部
};
int main(int argc, char* argv[])
{
Complex* array[1000];
clock_t t1,t2;
t1 = clock();
for (int i = 0; i < 5000; i++)
{
for (int j = 0; j < 1000; j++)
{
array[j] = new Complex(i,j);
}
for (int j=0;j<1000;j++)
{
delete array[j];
}
}
t2 = clock();
cout << double(t2-t1)/CLOCKS_PER_SEC << "s" << endl;
return 0;
}
代码,版本2
这次用一个内存管理类来托管内存的申请和释放,并且原有的Complex类上仅仅是重载了new/delete/new[]/delete[]这四个operator。放码过来:
#include <iostream>
#include <sys/types.h>
using namespace std;
class IMemoryManager{
public:
virtual void* allocate(size_t) = 0;
virtual void free(void*) = 0;
};
class MemoryManager: public IMemoryManager{
public:
MemoryManager(){
freestorehead = NULL;
ExpandPoolSize();
}
~MemoryManager(){
CleanUp();
}
void* allocate(size_t);
void free(void*);
private:
struct FreeStore{
FreeStore* next;
};
void ExpandPoolSize();
void CleanUp();
FreeStore* freestorehead;
};
MemoryManager gMemoryManager;
class Complex {
public:
Complex(double a, double b): r(a), c(b){}
inline void* operator new(size_t size){
return gMemoryManager.allocate(size);
}
inline void operator delete(void* object){
gMemoryManager.free(object);
}
inline void* operator new[](size_t size){
return gMemoryManager.allocate(size);
}
inline void operator delete[](void* object){
return gMemoryManager.free(object);
}
private:
double r;
double c;
};
void* MemoryManager::allocate(size_t size){
if (0==freestorehead){
ExpandPoolSize();
}
FreeStore* head = freestorehead;
freestorehead = head->next;
return head;
}
void MemoryManager::free(void* object){
FreeStore* head = static_cast<FreeStore*>(object);
head->next = freestorehead;
freestorehead = head;
}
const int POOLSIZE = 128;
void MemoryManager::ExpandPoolSize(){
size_t size = max(sizeof(Complex), sizeof(FreeStore*));
FreeStore* head = reinterpret_cast<FreeStore*>(new char[size]);
freestorehead = head;
for(int i=0; i<POOLSIZE; i++){
head->next = reinterpret_cast<FreeStore*>(new char[size]);
head = head->next;
}
head->next = 0;
}
void MemoryManager::CleanUp(){
FreeStore* nextPtr = freestorehead;
for(; nextPtr; nextPtr=freestorehead){
nextPtr = freestorehead;
freestorehead = freestorehead->next;
delete[] nextPtr;
}
}
int main(int argc, char* argv[])
{
Complex* array[1000];
clock_t t1,t2;
t1 = clock();
for (int i = 0; i < 5000; i++)
{
for (int j = 0; j < 1000; j++)
{
array[j] = new Complex(i,j);
}
for (int j=0;j<1000;j++)
{
delete array[j];
}
}
t2 = clock();
cout << double(t2-t1)/CLOCKS_PER_SEC << "s" << endl;
return 0;
}
分析
时间开销对比
g++ main_v1.cpp -o main_v1 -O3
./main_v1
0.217214s
g++ main_v2.cpp -o main_v2 -O3
./main_v2
0.026611s
两者的时间开销竟然相差一个数量级。
代码的正确性
其实new()申请内存的代码很不严谨,没有检查形参size是否会超过预设POOLSIZE大小,只不过通常情况下单次的size肯定小于POOLSIZE,但是极端情况下,或者一口气申请了多个变量的内存,可能会越界。另外,只适用于单线程。
以上内容来自IBM的一篇教程,还有很多内容没能看完和理解,挖坑带填:https://www.ibm.com/developerworks/aix/tutorials/au-memorymanager/index.html
C/C++内存管理器的更多相关文章
- PHP V5.2 中的新增功能,第 1 部分: 使用新的内存管理器
PHP V5.2:开始 2006 年 11 月发布了 PHP V5.2,它包括许多新增功能和错误修正.它废止了 5.1 版并被推荐给所有 PHP V5 用户进行升级.我最喜欢的实验室环境 —— Win ...
- TaskTracker节点上的内存管理器
Hadoop平台的最大优势就是充分地利用了廉价的PC机,这也就使得集群中的工作节点存在一个重要的问题——节点所在的PC机内存资源有限(这里所说的工作节点指的是TaskTracker节点),执行任务时常 ...
- STL内存管理器的分配策略
STL提供了很多泛型容器,如vector,list和map.程序员在使用这些容器时只需关心何时往容器内塞对象,而不用关心如何管理内存,需要用多少内存,这些STL容器极大地方便了C++程序的编写.例如可 ...
- BBS项目详解(forms快速创建登陆页面,登陆验证、通过阅读器进行头像上传的预览、内存管理器)
BBS项目涉及的知识点 django中知识点 钩子函数(局部钩子和全局钩子) 1.局部钩子就是用来做合法性校验,比如用户名有没有被使用等 2.全局的就是用来做对比校验,比如两次输入的密码是否一致 3. ...
- DLL何时需共享内存管理器
Delphi创建DLL时,IDE自动生成的文档中写得很清楚,当在DLL中以动态数组或String做为参数或返回值时(即RTL自动维护的数据类型),请在每个工程文件的第一个单元加上ShareMem.这样 ...
- spark内存管理器--MemoryManager源码解析
MemoryManager内存管理器 内存管理器可以说是spark内核中最重要的基础模块之一,shuffle时的排序,rdd缓存,展开内存,广播变量,Task运行结果的存储等等,凡是需要使用内存的地方 ...
- Netty内存管理器ByteBufAllocator及内存分配
ByteBufAllocator 内存管理器: Netty 中内存分配有一个最顶层的抽象就是ByteBufAllocator,负责分配所有ByteBuf 类型的内存.功能其实不是很多,主要有以下几个重 ...
- android的低内存管理器【转】
本文转载自:http://blog.csdn.net/haitaoliang/article/details/22092321 版权声明:本文为博主原创文章,未经博主允许不得转载. 安卓应用不用太在意 ...
- LevelDB(v1.3) 源码阅读之 Arena(内存管理器)
LevelDB(v1.3) 源码阅读系列使用 LevelDB v1.3 版本的代码,可以通过如下方式下载并切换到 v1.3 版本的代码: $ git clone https://github.com/ ...
随机推荐
- linux 安装matlab
转自: https://www.cnblogs.com/Amedeo/archive/2018/06/03/9129925.html 一.下载“Crack”和”ISO”文件 下载地址如下所示:http ...
- 关于iframe的相关操作
1.判断当前页面是否在iframe当中 if (top.location != self.location) { alert("in iframe") }
- Pytorch tutorial 之Datar Loading and Processing (2)
上文介绍了数据读取.数据转换.批量处理等等.了解到在PyTorch中,数据加载主要有两种方式: 1. 自定义的数据集对象.数据集对象被抽象为Dataset类,实现自定义的数据集需要继承Dataset. ...
- 新版本微信导致的ios表单bug
解决方法如下: $(document).delegate('input, textarea, select', 'blur', function(){ setTimeout(function(){ $ ...
- requests库入门10-超时,错误与异常
在实际发布到生产上的接口测试代码,都会加上超时的设置,当服务器超过一定时间没有响应,会报出超时异常.因为requests会自动等待响应.如果不加上超时的设置,可能脚本会一直卡在那里.. 超时设置在请求 ...
- 解决64bit不能连接access的问题
原有的程序迁移至64位,结果调用数据库时出错,原因是jet驱动没有64位的,得换用64位的驱动程序: 1. 下载运行 AccessDatabaseEngine_x64.exe (http://ww ...
- HashMap多线程put后get为null和多线程put的时候可能导致元素丢失
一.多线程put后get为null 源码定位 void transfer(Entry[] newTable) { Entry[] src = table; int newCapacity = newT ...
- ECC加密算法入门介绍 --- 看雪
标 题:ECC加密算法入门介绍 作 者:zmworm 时 间:2003/05/04 08:32pm 链 接:http://bbs.pediy.com ECC加密算法入门介绍 作者 :ZMWorm[C ...
- UVA 11796
题意: 有两个狗, 按照 多边形跑,不知道两条狗的速度,但是狗是同时出发,同时到达终点的 输出两条狗的 最大相距距离 - 最小相距距离: 思路 : 用物理的相对运动来计算, 每次只计算 两条狗的直线 ...
- WebSocket服务端和客户端使用
using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Net;usi ...