C++ Memory System Part3 : 优化
前面的系列我们讲了自定义new和delete操作,其中针对deleteArray的问题还有需要优化的地方。我们这次就针对POD类型进行一次优化。
下面的代码是针对POD类型的模板函数实现,分别为NewArrayPOD和DeleteArrayPOD:
template <typename T, class ARENA>
T* NewArrayPOD(ARENA& arena, size_t N, const char* file, int line)
{
return static_cast(arena.Allocate(sizeof(T)*N, file, line));
} template <typename T, class ARENA>
void DeleteArrayPOD(T* ptr, ARENA& arena)
{
arena.Free(ptr);
}
从上面可以看出,针对POD类型,我们不需要调用析构函数,只需要将内存释放即可,所以其区别于非POD类型。但是如果实现了POD和非POD两个版本的函数,该如何让我们的宏根据类型自己调用合适的函数呢?
我们采用的方式是放弃NewArrayPOD和DeleteArrayPOD这种另外实现一个函数的方式,而是重载NewArray和DeleteArray函数,使宏根据参数来正确调用对应的函数。我们首先要实现的是一个traits-class,它用来判断一个类型是不是POD类型。这可以通过定义一个基础模板类和一些特化版本来实现,代码如下:
template <typename T>
struct IsPOD
{
static const bool Value = false;
}; template <>
struct IsPOD<char>
{
static const bool Value = true;
}; template <>
struct IsPOD<int>
{
static const bool Value = true;
}; // etc.
对于任何一个给定的类型T,我们可以通过编译期常量IsPOD<T>::value来确定T是否为一个POD类型。当然了,如果使用了C++11及以后的标准,标准库中就实现了std::is_pod。
两个重载版本的函数实现如下:
template <typename T, class ARENA>
T* NewArray(ARENA& arena, size_t N, const char* file, int line, NonPODType)
{
// implementation for non-POD types
} template <typename T, class ARENA>
T* NewArray(ARENA& arena, size_t N, const char* file, int line, PODType)
{
// implementation for POD types
} template <typename T, class ARENA>
void DeleteArray(T* ptr, ARENA& arena, NonPODType)
{
// implementation for non-POD types
} template <typename T, class ARENA>
void DeleteArray(T* ptr, ARENA& arena, PODType)
{
// implementation for POD types
}
当然了,看到上面的代码后,你可能会问,C++的重载是根据类型来的,又不是根据值,我们不能只通过一个true和一个false来重载函数。所以为了让上面的代码能够正确工作,我们需要再实现一个模板黑魔法称为type-based dispatching。
template <bool I>
struct IntToType
{
}; typedef IntToType<false> NonPODType;
typedef IntToType<true> PODType;
这样,我们就可以将上一节中的宏定义修改为:
// old version
#define ME_NEW_ARRAY(type, arena) NewArray<TypeAndCount<type>::Type>(arena, TypeAndCount<type>::Count, __FILE__, __LINE__) // new version
#define ME_NEW_ARRAY(type, arena) NewArray<TypeAndCount<type>::Type>(arena, TypeAndCount<type>::Count, __FILE__, __LINE__, IntToType<IsPOD<TypeAndCount<type>::Type>::Value>())
有点小长,但是如果理解了背后的技巧和原理,实现起来其实并不复杂。但是我们还有最后一个问题,就是在宏定义#define OM_DELETE_ARRAY(object, arena) DeleteArray(object, arena)中不能直接使用Is_POD<T>方法,因为obejct本身是一个值,不是一个一个类型,我们又不想显式的再用一个参数来制定类型,因为编译器已经知道了类型,所以我们要做的就是让编译器自己推到出类型再调用DeleteArray函数,所以我们只需将DeleteArray函数封装在一个模板函数中,就可以实现这一点,代码如下:
template <typename T, class ARENA>
void DeleteArray(T* ptr, ARENA& arena)
{
DeleteArray(ptr, arena, IntToType<IsPOD<T>::Value>());
}
至此为止,我们对POD和非POD类型的优化工作已经结束,现在我们可以高效的使用自定义的OM_NEW_ARRAY和OM_DELETE_ARRAY了。
参考link:
https://stoyannk.wordpress.com/2018/01/10/generic-memory-allocator-for-c-part-3/
https://bitsquid.blogspot.com/2010/09/custom-memory-allocation-in-c.html
https://blog.molecular-matters.com/
C++ Memory System Part3 : 优化的更多相关文章
- 内存泄漏 Memory Leaks 内存优化 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- gem5: 使用ruby memory system中的mesh结构 出现AssertionError错误
问题:在使用ruby memory system中的mesh结构測试时,出现例如以下错误: Traceback (most recent call last): File "<stri ...
- PatentTips - Mechanisms for strong atomicity in a transactional memory system
BACKGROUND Advances in semi-conductor processing and logic design have permitted an increase in the ...
- Bit error testing and training in double data rate (ddr) memory system
DDR PHY interface bit error testing and training is provided for Double Data Rate memory systems. An ...
- Power management in semiconductor memory system
A method for operating a memory module device. The method can include transferring a chip select, co ...
- armv8 memory system
在armv8中,由于processor的预取,流水线, 以及多线程并行的执行方式,而且armv8-a中,使用的是一种weakly-ordered memory model, 不保证program or ...
- C++ Memory System Part2: 自定义new和delete
在第一部分中,我们介绍了new / delete的具体用法和背后的实现细节,这次我们将构建我们自己的小型工具集,可以使用我们自定义的allocator类来创建任意类型的实例(或者实例数组),我们需要做 ...
- 雪花算法对System.currentTimeMillis()优化真的有用么?
前面已经讲过了雪花算法,里面使用了System.currentTimeMillis()获取时间,有一种说法是认为System.currentTimeMillis()慢,是因为每次调用都会去跟系统打一次 ...
- C++ Memory System Part1: new和delete
在深入探索自定义内存系统之前,我们需要了解一些基础的背景知识,这些知识点是我们接下来自定义内存系统的基础.所以第一部分,让我们来一起深入了解一下C++的new和delete家族,这其中有很多令人吃惊的 ...
随机推荐
- Log--事务日志
由于日志是顺序写入,而修改数据分散在数据库各个页面,属于随机写入,而磁盘顺序写入速度远高于随机写入,因此主流数据库都采用预写日志的方式来确保数据完整性 1.日志记录的是数据的变化而不是引发数据的操作2 ...
- Highsoft.Highcharts 5.0.6439.38401 key
Highcharts .NET allows developers to make charts using Highcharts API with the Microsoft .NET Framew ...
- 快速下载android源码
众所周知的原因,android源码被墙了,还好国内有不少镜像,这里使用清华提供的镜像. 以下内容转自: https://wiki.tuna.tsinghua.edu.cn/MirrorUsage/an ...
- day7学python 初识简单模板
初识简单模板 模块与包 1.模块:用来从逻辑上组织python代码(变量,函数,类,逻辑:实现功能),本质是.py结尾的文件 但导入的模块名,无.py 2.包:从逻辑上组织模块,本质就是目录(含有_i ...
- MongoDB 深入学习 -- ReplSet,Sharding,Security,Aggregation,Command
萌新最近在对付MongoDB,因此每天都在翻官方文档,这里随便做点笔记 ReplSet 与 Sharding ReplSet 是副本集,也就是主从集合.可以用来做负载均衡,数据热备份.副本集的配置相对 ...
- Python爬虫从入门到放弃 之 Scrapy框架中Download Middleware用法
这篇文章中写了常用的下载中间件的用法和例子.Downloader Middleware处理的过程主要在调度器发送requests请求的时候以及网页将response结果返回给spiders的时候,所以 ...
- 【python】collections模块(有序字典,计数器,双向队列)
collections模块基本介绍 我们都知道,Python拥有一些内置的数据类型,比如str, int, list, tuple, dict等, collections模块在这些内置数据类型的基础上 ...
- linux下配置apache多站点访问-小案例
一级域名(baidu.com)也叫作顶级域名,注册一级域名是需要付费的. 而二级域名(image.baidu.com)是一级域名的延伸,所以只要购买了一级域名,二级域名是可以任意配置的. 其实(www ...
- 当AVPlayer在被释放之后,Player一直监听的时间没有被移除,提示错误的解决办法
Xcode Consolu打印出来的提示: An instance 0x156608c0 of class AVPlayer was deallocated while key value obser ...
- Tensorflow可视化MNIST手写数字训练
简述] 我们在学习编程语言时,往往第一个程序就是打印“Hello World”,那么对于人工智能学习系统平台来说,他的“Hello World”小程序就是MNIST手写数字训练了.MNIST是一个手写 ...