最近看了一篇内存分配器的论文,原理很简单,但是里面的数学论证还没看懂,这次先简单写一下原理和用到的API。

内存分配器是用于封装操作系统提供的底层API,给应用程序提供动态内存的。内存不断申请释放后,往往会形成内存碎片。当需要申请一段较大的内存时,当前剩余内存总量是够的,但是被当前申请的内存块隔断成一个个小隔间,内存分配器无法给出指定长度的内存。这时就只能向操作系统重新申请,或者对应用程序返回分配失败了。

图片来自这里

如上图所示,不断申请内存后,内存占用如Figure 2所示。应用程序释放部分内存后,形成Figure 3。前面的两个空闲内存块,就只能用来放小的内存对象了。即使总内存足够,也因为中间内存对象的隔断,无法分配出足够大的内存。

为了避免内存碎片增多,Mesh提出了内存页合并的想法。在现代的Linux系统上,内存页一般以4K大小分配,假设页A有碎片,页B也有碎片,但是页A和页B的碎片相对于页头的偏移刚好不重叠,那就可以将两者合成一页,腾出完整的一页来分配较大的内存。见下图:

(图来自论文)

这种合并的方法有一个问题,c/c++的应用程序可能直接存下了对象的地址,所以内存合并后,原有分配对象的地址不能变。作者用了一个巧妙的方法来解决这个问题:

1. 作者用内存文件系统创建了一个内存文件(mkstemp)

2. 通过mmap api创建一个1:1的内存映射,将第一步的文件映射为一块内存(mmap,这里需要设为MAP_SHARED, 如果设为 MAP_PRIVATE则重映射后B页内容会丢掉)

3. 假设算法发现有A和B两页内存可进行合并,则将B中存的对象用memcpy拷贝到A里去(memcpy或者普通的赋值操作)

4. 通过mmap api将B页重新映射到A页对应的文件偏移上(mmap,这里需要设为MAP_FIXED,表示新的内存映射就用这个地址开始)

这样应用程序依然可以通过原有的内存地址访问原有的内存对象,而对象实际上已经移动到新的位置了。

上面的步骤我做了个小实验验证了一下,的确可行。作者论文里提到修改页表来完成,之前纠结了很久为什么应用程序可以改页表,不是操作系统维护页表的吗?可以改页表不就可以碰物理内存了?……才知道原来mmap可以这样玩233333

Mesh内存分配器的mmap小技巧的更多相关文章

  1. arc下内存泄漏的解决小技巧

    一定要注意,我们运行app时,一定要关心内存的使用,尽量不要超过20M,即使有很多图片要显示也绝对不能超过30M.所以运行自己开发的app时多关心内存的使用是个很好的习惯. 对于性能,内存的优化,这个 ...

  2. Java内存管理的9个小技巧

    Java内存管理的9个小技巧很多人都说“Java完了,只等着衰亡吧!”,为什么呢?最简单的的例子就是Java做的系统时非常占内存!一听到这样的话,一定会有不少人站出来为Java辩护,并举出一堆的性能测 ...

  3. 关于Java内存管理的几个小技巧

    这里将介绍几则Java内存管理的小技巧,让你让你从Java入门开始告别陋习,为Java程序提速.有不少人都说"Java完了,只等着衰亡吧!",为什么呢?最简单的的例子就是Java做 ...

  4. 填坑总结:python内存泄漏排查小技巧

    摘要:最近服务遇到了内存泄漏问题,运维同学紧急呼叫解决,于是在解决问题之余也系统记录了下内存泄漏问题的常见解决思路. 本文分享自华为云社区<python内存泄漏排查小技巧>,作者:luti ...

  5. Nah Lock: 一个无锁的内存分配器

    概述 我实现了两个完全无锁的内存分配器:_nalloc 和 nalloc.  我用benchmark工具对它们进行了一组综合性测试,并比较了它们的指标值. 与libc(glibc malloc)相比, ...

  6. [转]STL的内存分配器

    题记:内存管理一直是C/C++程序的红灯区.关于内存管理的话题,大致有两类侧重点,一类是内存的正确使用,例如C++中new和delete应该成对出现,用RAII技巧管理内存资源,auto_ptr等方面 ...

  7. CoreCLR源码探索(三) GC内存分配器的内部实现

    在前一篇中我讲解了new是怎么工作的, 但是却一笔跳过了内存分配相关的部分. 在这一篇中我将详细讲解GC内存分配器的内部实现. 在看这一篇之前请必须先看完微软BOTR文档中的"Garbage ...

  8. 理解 glibc malloc:主流用户态内存分配器实现原理

    https://blog.csdn.net/maokelong95/article/details/51989081 Understanding glibc malloc 修订日志: 2017-03- ...

  9. 内存分配器 (Memory Allocator)

    对于大多数开发人员而言,系统的内存分配就是一个黑盒子,就是几个API的调用.有你就给我,没有我就想别的办法. 来UC前,我就是这样觉得的.实际深入进去时,才发现这个领域里也是百家争鸣.非常热闹.有操作 ...

随机推荐

  1. ldap 导出、导入ldif数据

    ldap 导出.导入ldif数据有如下方式: 1.dsadm(速度快,需要停止ldap实例) 2.dsconf(速度慢,需要保持ldap实例开启) windows导出.导入需要加上参数--unsecu ...

  2. Java编程思想--控制执行流程

    java控制流程设计的关键字包括if-else,while,do-while,for,return,break,continue以及switch.(go-to) 1.while在迭代之前计算一次布尔表 ...

  3. GDAL——命令使用专题——ogrinfo命令

    GDAL——命令使用专题——ogrinfo命令 前言 GDAL(Geospatial Data Abstraction Library)是一个在X/MIT许可协议下的开源栅格空间数据转换库.它利用抽象 ...

  4. import com.sun.org.apache.xerces.internal.impl.dv.util.Base64报错

       该类不属于JDK标准库范畴,但在JDK中包含了该类,可以直接使用.但是在eclipse中直接使用却找不到该类. 以下是解决方法步骤: Properties-->JavaBulid Path ...

  5. vue中几种常见技巧

    1.校验延迟:点击进入页面不希望校验必填字段this.$nextTick(() => { this.$refs.formRules.clearValidate() })2.$on $emit $ ...

  6. http/1.0/1.1/2.0与https的比较

    HTTP是HyperText Transfer Protocol的缩写,译为超文本传输协议.是一种应用于OSI七层模型中应用层的协议,是我们平常互联网网络通信传输的基础.它的作用就是规定了服务器和客户 ...

  7. 【js高程学习笔记】关于变量值和函数参数

    变量包含了两种不同类型的值: 基本类型 (Undefined.null.Boolean.Number.string都属于基本类型) 引用类型 (对象) 两种值在赋值上不同的是: 将一个引用类型的值(对 ...

  8. Delphi做验证码登录窗口

    在五月麦田的帮助下做成了,感觉挺好,验证码输入的时候需要大写: 组件:LabelEdit 3个  Button 2个  image 1个. 代码如下: unit Unit1; interface us ...

  9. Qunar入职前自学笔记

    Q1. 什么是html,html发展历程 hyperText markup language 超文本标记语言 HTML是用于描述网页文档的标记语言.现在我们常常习惯于用数字来描述HTML的版本(如:H ...

  10. java xml 转 json

    <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> ...