最近看了一篇内存分配器的论文,原理很简单,但是里面的数学论证还没看懂,这次先简单写一下原理和用到的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. python 调用js代码

    Python2   安装pyv8 pip install-egit://github.com/brokenseal/PyV8-OS-X#egg=pyv8 from pyv8 import PyV8 c ...

  2. 基于Live555实现RtspServer及高清高分辨率和高码率视频传输优化

    基于Live555实现RtspServer及高清高码率视频传输优化 最近做了一些pc和嵌入式平台的RTSP服务器项目,大多数的要求是简单但是功能全面,并且性能还要强劲.综合考虑后,基本都是在基于liv ...

  3. Spring Boot :邮件服务

    简单使用 1.pom 包配置 pom 包里面添加 spring-boot-starter-mail 包引用 <dependencies> <dependency> <gr ...

  4. v模拟器(华为、H3C)点滴

    华为模拟器:eNSP V100R002C00B500 安装问题: 1)环境为WIN10,64位专业版 2)安装完成后可以打开界面,但是新建一个设备后,打不开,一直不停的#号 3)解决:手工点击Virt ...

  5. min_25筛题目总结

    看了网上众多博客后,我才发现,实现min_25只有脑子,没有代码. 当然可能是我太ruo了. min_25是一种想法,不是算法. 不要尝试套模板,因为很多题目并没有什么用. 最重要的一点,g不要看成是 ...

  6. CodeForces - 1040B Shashlik Cooking(水题)

    题目: B. Shashlik Cooking time limit per test 1 second memory limit per test 512 megabytes input stand ...

  7. 使用该方法在ubuntu下安装flashplayer的rpm包

    Ubuntu的软件包格式是deb,如果要安装rpm的包,则要先用alien把rpm转换成deb. sudo apt-get install alien #alien默认没有安装,所以首先要安装它 su ...

  8. Python面向对象基础知识

    面向对象是一种编程方式,此编程方式的实现是基于对类和对象的使用 类是一个模板,模板中包装了多个“函数”供使用(可以讲多函数中公用的变量封装到对象中) 对象,根据模板创建的实例(即:对象),实例用于调用 ...

  9. DDD 学习记录

    1.领域模型建立    set 最好是受保护 2.CQRS   建议   查询可以直接从数据层获取: 3.领域服务 包含 不合适放在其他实体里面的方法,包含比较多实体操作的方法: 4.实体 里面的方法 ...

  10. Spark Streaming的容错和数据无丢失机制

    spark是迭代式的内存计算框架,具有很好的高可用性.sparkStreaming作为其模块之一,常被用于进行实时的流式计算.实时的流式处理系统必须是7*24运行的,同时可以从各种各样的系统错误中恢复 ...