【数据结构】动态内存管理_冬日新雨的博客-程序员秘密

技术标签: python  内存管理  数据结构  Python  

动态内存管理是和操作系统息息相关的一个活动,现在的计算机的内存分配和回收基本上都由OS来维护管理,但是一些高级程序语言的内存回收和分配都还是由程序员来管理,比如C和C++,有malloc方法,也总有构造函数和析构函数。但是有一些语言就不需要,比如Python。

系统每次对申请内存的对象分配一段地址连续的内存块,如果已经被占用了,就叫做占用块,如果还没被分配掉,就叫做可利用空间块或者空闲块。在回收内存之后,系统的整个内存块会出现参差不齐的状态,这时候就需要用到动态内存管理了。

一、 可利用空间表

可利用空间表是系统中都在使用的一种内存管理工具,针对不同的情况需要设定不同的链表数据结构。
1、 每次分配的内存大小是一样的,这时候就使用一个链栈即可,把内存分为大小相同的块,如果有应用程序来申请,就从栈顶分配一个内存块出去,如果回收回来一个,就放入栈顶。
2、 系统每次分配给用户的内存块的大小分为若干种规格,且一般都是2的次方。这种情况下采用可利用空间表,且利用伙伴系统对内存进行管理。
3、 系统每次按需分配给用户内存块,大小随机。这种情况下同样适用可利用空间表,只不过数据结构会有所变化,管理手段也有不同。

二、 可利用空间表的几种数据结构

1、普通可利用空间表:即一个可利用空间链表,其中包括以下几个字段,tag标识该段是否被使用,type或size标识该段的内存空间大小,link标识后继的内存块,space即存储的空间。
2、采用边界标识法的可利用空间表:相比普通可利用空间表要复杂一些,主要的字段有llink即该内存块的前驱,rlink是后继,tag 和 size 不变,uplink标识也是指针,指向本链表结点,其值就是该空闲内存块的首地址。分配的时候需要修改链表,也就是修改若干指针的地址;回收的时候要考虑相邻的内存块是否是空闲块,如果是的话,就要合并。
3、采用伙伴系统的可利用空间表:通过一个2的次方的指针数组来分别指示不同大小块的链表,分配的时候也是修改链表,但是在回收的时候,同样存在相邻空闲块合并的操作,但是如果两个相邻块不是同一个大的内存块分化出来的,则不合并,因为容易造成错误。

三、分配内存策略

1、就近分配,在搜索可利用空间链表的过程中,遇到的第一个符合应用程序申请要求的内存块就被系统选中分配出去。
2、最优化匹配,在搜索可利用空间表的过程中,要选择空间最接近申请要求的内存块,这样能够避免块内存的浪费。这种分配方法较为复杂,也就是说在分配的时候需要修改指针,回收的时候还是需要修改指针,但是好处是比较适合那些申请内存大小千差万别的系统。
3、最差匹配,在搜索可利用空间表的过程中,要选择最不接近申请要求的内存块,也就是最大的那一个空闲块。这个策略比较适合每次申请的内存块差不多大小的系统。

四、 无用单元收集

1、 设置内存计数器,如果指向某内存单元的指针计数为0,则释放该单元;
2、 收集无用单元:主要包括两个步骤,给所有的占用块添加mark域,当mark为0时表示该结点还没有被判断过是否要收集无用单元,mark为1表示已经被系统考察过了;然后,遍历所有的占用块,这种标记遍历算法有若干种,具体不述了。

五、 存储紧缩

无用单元收集的过程主要就是修改单元中的指针和某些结点的标记值,而存储紧缩则要将数据按照内存地址进行整体迁移,其过程相当于搬家。这样能完整地改善内存块犬牙交错的状态。

六、Python的内存管理

  1. 对象的引用计数机制
    Python内部使用引用计数,来保持追踪内存中的对象,所有对象都有引用计数。
    引用计数增加的情况:
    1,一个对象分配一个新名称
    2,将其放入一个容器中(如列表、元组或字典)
    引用计数减少的情况:
    1,使用del关键字语句对对象别名显示的销毁
    2,引用超出作用域或被重新赋值
    sys.getrefcount( )函数可以获得对象的当前引用计数
    多数情况下,引用计数比你猜测得要大得多。对于不可变数据(如数字和字符串),解释器会在程序的不同部分共享内存,以便节约内存。
  2. 垃圾回收
    1,当一个对象的引用计数归零时,它将被垃圾收集机制处理掉,也就是无用单元收集的一种策略。
    2,当两个对象a和b相互引用时,del语句可以减少a和b的引用计数,并销毁用于引用底层对象的名称。然而由于每个对象都包含一个对其他对象的应用,因此引用计数不会归零,对象也不会销毁。(从而导致内存泄露)。为解决这一问题,解释器会定期执行一个循环检测器,搜索不可访问对象的循环并删除它们。
  3. 内存池机制
    python提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统。
    1,Pymalloc机制。为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。
    2,Python中所有小于256个字节的对象都使用pymalloc实现的分配器,而大的对象则使用系统的malloc。
    3,对于Python对象,如整数,浮点数和List,都有其独立的私有内存池,对象间不共享他们的内存池。也就是说如果你分配又释放了大量的整数,用于缓存这些整数的内存就不能再分配给浮点数。
  4. 分代技术
    分代回收的整体思想是:将系统中的所有内存块根据其存活时间划分为不同的集合,每个集合就成为一个“代”,垃圾收集频率随着“代”的存活时间的增大而减小,存活时间通常利用经过几次垃圾回收来度量。
    Python默认定义了三代对象集合,索引数越大,对象存活时间越长。
    举例:
    当某些内存块M经过了3次垃圾收集的清洗之后还存活时,我们就将内存块M划到一个集合A中去,而新分配的内存都划分到集合B中去。当垃圾收集开始工作时,大多数情况都只对集合B进行垃圾回收,而对集合A进行垃圾回收要隔相当长一段时间后才进行,这就使得垃圾收集机制需要处理的内存少了,效率自然就提高了。在这个过程中,集合B中的某些内存块由于存活时间长而会被转移到集合A中,当然,集合A中实际上也存在一些垃圾,这些垃圾的回收会因为这种分代的机制而被延迟。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/dongrixinyu/article/details/78639292

智能推荐

关于无法找到 com.sun.image.codec.jpeg 的解决方法_田辛 | 田豆芽的博客-程序员秘密

今天在运行下面代码的时候,发生了包找不到的错误。import com.sun.image.codec.jpeg.JPEGCodec;import com.sun.image.codec.jpeg.JPEGImageEncoder;/* 中途略 */JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); enc

Skype豪赌VoIP 电话革命蓄势待发--Skype通话质量还不错哦!_iteye_4537的博客-程序员秘密

深度报道:Skype豪赌VoIP 电话革命蓄势待发 作者: ZDNet ChinaCNETNews.com.cn 2004-10-10 08:31 AM<!-- BEGIN:STORY -->CNET科技资讯网 10月10日国际报道:加州圣荷西科技公司职员孙群第一次听说Skype 提供免费、高品质的互联网电话服务时,他以为那大概又是夸大不实的宣传。 孙群常以科技早期采纳者...

云文档能代替服务器吗,云存储能代替服务器存储吗_mogego七海的博客-程序员秘密

云存储能代替服务器存储吗 内容精选换一换本章节主要介绍云硬盘、弹性文件服务、对象存储服务等存储服务,让您更好的了解这些存储服务。使用存储容灾服务前,请您先了解表1中描述的使用限制。在生产站点可用区整个AZ故障时,可通过容灾演练功能恢复服务器业务。首次切换/故障切换和容灾演练操作后,登录弹性云服务器有哪些注意事项?云存储能代替服务器存储吗 相关内容ModelArts为用户提供了多种常见的预置引擎,但...

Pandas的DataFrame某一列是字符串类型,如何按照字符串的长度对该DataFrame排序_别闹'的博客-程序员秘密

数据如下:df = pd.DataFrame({ 'name': ['六个六撒', '张三', '李四全', '王'], 'age': ['6', '3', '2', '5']})按照name列中元素的长度由小到大排序:df = pd.DataFrame({ 'name': ['六个六撒', '张三', '李四全', '王'], 'age': ['6',...

2018 年 2 月份 GitHub 上的热门开源项目_Linux云计算数据自学的博客-程序员秘密

2 月份 GitHub 上最热门的开源项目又出炉了,又有哪些新的项目挤进热门榜单了呢,一起来看看。1nocodehttps://github.com/kelseyhightower/nocode Star 16256这是 2 月份新出炉的项目,可以说是 2018 年最火的佛系编程了,这个项目里面没有一行代码,它的 description 是这样的:The best way to write sec

Java读取文件夹下的所有文件名和文件内容_木子_coder的博客-程序员秘密_java 读取文件夹内容

**Java 读取文件夹下的所有文件名和文件内容**1. 读取指定目录下的每一个文件的文件名和文件内容2. 并把文件名作为key,文件内容为value 存储在map集合中3. 通过遍历map集合拿到我们需要的文件名和文件内容**/** * Java读取文件夹下的所有文件名和文件 * @author Younger * */public class ReadFile { public static void main(String[] args) { Map<Strin

随便推点

项目开发总结报告_LuckyZhouStar的博客-程序员秘密_项目开发总结报告

项目开发总结报告1引言1.1编写目的   机房收费系统的开发基本已经完成,此项目开发总结报告,是在分析我们在开发过程总的经验和教训,为我们以后的开发项目积累经验,从而减少成本。     预期读者:所有参与项目相关人员1.2背景项目的名称:机房收费系统任务提出者:机房管理老师开发者:提高班开发小组安装需求

ASP.NET分页显示技术_嘿牛的博客-程序员秘密_asp.net 分页显示

最近一直在忙着有关计算机中心的网站。中间遇到了一个小问题就是分页显示的问题。网上也有不少相关的技术与控件,但是我不想那么麻烦去看那些代码。所以就自己写了一些。希望大家能多多指导一些。我从数据库读取时,直接读到相应的数据。只取前多少条。中间需要前台js与后台cs的交互。网上有好多关于这方面的介绍。下面是我的代码:前台:                             

freemarker学习网站_fytcm的博客-程序员秘密

freemarker学习网站http://www.656463.com/article/280初试FreeMarker模板的一些问题http://724073277.iteye.com/blog/1450002一篇很全面的freemarker教程http://relive123-yahoo-com-cn.iteye.com/blog/818013...

unread support_tangxuankai的博客-程序员秘密

从MTK里面提取出来的图标未读提示角标功能:创建文件UnreadLoader.javapackage com.android.launcher3;import android.content.BroadcastReceiver;import android.content.ComponentName;import android.content.ContentResolver;i

nodejs实现用户邮箱注册__Kay_的博客-程序员秘密_nodejs邮箱注册

前言本篇博文以实战的角度描述用户注册和密码找回的实现过程.整个项目使用koa2框架搭建.用户注册的流程简述如下:用户向接口地址发送三个字段用户名user_name,密码password和邮箱email.后端接受后向数据库中的用户表插入一条新的记录,但设置该条用户记录的状态为不可用.随后向用户邮箱发送一个校验的url,用户打开邮箱里面的地址跳转之后,数据库对应的那条用户记录状态由不可用置为可用,至此...

微信小程序开发(原生)_探鱼不是鱼的博客-程序员秘密_原生小程序开发

简介微信小程序(wei xin xiao cheng xu),简称小程序,英文名Mini Program,是一种不需要下载安装即可使用的应用 ( 张小龙对其的定义是无需安装,用完即走,实际上是需要安装的,只不过小程序的体积特别小, 下载速度很快,用户感觉不到下载的过程 )2017年1月9日0点,万众瞩目的微信第一批小程序正式低调上线小程序刚发布的时候要求压缩包的体积不能大于1M,,否则无法通过,在2017年4月做了改进,由原来的1M提升到2M...

推荐文章

热门文章

相关标签