最近看了一篇内存分配器的论文,原理很简单,但是里面的数学论证还没看懂,这次先简单写一下原理和用到的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. IntelliJ IDEA 注册码——亲测有效

    链接地址:http://idea.lanyus.com 使用时需要将“0.0.0.0 account.jetbrains.com”添加到hosts文件中,mac操作hosts文件可以参考链接: htt ...

  2. 13、属性的get(存)和set(取)器

    原因:当对年龄重新进行赋值的时候就会调用set方法,然后进行判断,如果赋值小于10就会抛出异常.

  3. iOS 性能优化总结

    卡顿产生的原因 在 VSync信号到来后,系统图形服务会通过 CADisplayLink等机制通知 App,App主线程开始在 CPU中计算显示内容,比如视图的创建.布局计算.图片解码.文本绘制等.随 ...

  4. day 09初始函数

    # with open('小护士班主任',encoding='utf-8') as f,open ('小护士班主任.bak','w',encoding='utf-8')as f2: # for lin ...

  5. php中excel以及cvs等导入以及导出

    一般网站后台都有人员导入或者是订单导出之类的操作,今天分享一下几种php excel cvs等文件导入导出的办法. 第一种比较简单的,自己写的,不引用任何excel类.但是会有bug,代码如下: 首先 ...

  6. python小总结3(异常、单例设计模式)

    一.异常 AttributeError:试图访问一个对象没有的成员[属性和方法] ValueError:值错误,传入了一个不期望的值 ImportError:无法导入模块或者包:基本上路径问题 Ind ...

  7. Forth-83 多任务解析

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

  8. layui从子iframe打开父iframe的tab选项卡

    数据表格字段: {field: 'novelId', title: '小说ID',width:100,templet: '<div><a href="javascript: ...

  9. console.log()中的%d,%s等代表的输出类型

    在console.log()或console.debug()中输出时会有%d,%s等符号. %s for a String value 字符类型 %d or %i for a Integer valu ...

  10. ORM-Model操作

    django为使用一种新的方式,即:关系对象映射(Object Relational Mapping,简称ORM). django中遵循 Code Frist 的原则,即:根据代码中定义的类来自动生成 ...