从Python的源码来解析Python下的freeblock


Posted in Python onMay 11, 2015

1 引言

在python内存管理中,有一个block的概念。它比较类似于SGI次级空间配置器。
首先申请一块大的空间(4KB),然后把它切割成一小份(8, 16 一直到512)。
当有内存申请的请求时候,简单的流程是:根据大小找到对应的block,然后在freeblock 上给它一份。

2 问题

整个过程是一种比较自然的slab分配方式。但当我读到这段代码时,却感到疑惑:

static void* _PyObject_Malloc(void* ctx, size_t nbytes)
{
    ...
  pool->freeblock = (block*)pool + pool->nextoffset;

    pool->nextoffset += INDEX2SIZE(size);
    *(block **)(pool->freeblock) = NULL; // [1]
    ...
}

freeblock指向空闲的链表,为它赋值很好理解。但是为什么要加上代码1处那一句!
对C比较熟悉的童鞋很容易能看出它的作用,它在为*freeblock赋值为NULL。

但是为什么要这么做?
直到看到内存回收的代码:

static void _PyObject_Free(void* ctx, void*p)
{
  ...
  *(block**)p = lastfree = pool->freeblock;
  pool->freeblock = (block*)p;
  ...
}

回想一下SGI次级空间配置,它需要一个链表,指向block中可用的小块。因为这些快,是离散的,只有用指针才能索引它。
在SGI次级空间配置中,是用一个union,达到了节省空间的目的:有数据时,它存储着真正的数据;没有数据时,它就变成指向下一块可用内存的指针:

union __Obj {
  union __Obj* free_list_link;
  char client_data[];
};

这样一想,问题就变得很明显了。freeblock指向一个链表,链表的next域就由它自己来索引。
在_PyObject_Free中,内存p是要被回收的,它应该插在freeblock的链表头,freeblock被更新指向它。同时,p指向原来freeblock指向的内容,这是一个很简单的链表插入操作。
这样在遍历的时候,我们就可以用freeblock = * freeblock的方式来工作了。
如下图所示:

从Python的源码来解析Python下的freeblock

Python 相关文章推荐
Python中optparse模块使用浅析
Jan 01 Python
在Python的Django框架中获取单个对象数据的简单方法
Jul 17 Python
Python实现多线程HTTP下载器示例
Feb 11 Python
python使用mysql数据库示例代码
May 21 Python
Python3.6安装及引入Requests库的实现方法
Jan 24 Python
浅析PHP与Python进行数据交互
May 15 Python
python实现五子棋游戏
Jun 18 Python
python二维码操作:对QRCode和MyQR入门详解
Jun 24 Python
更新pip3与pyttsx3文字语音转换的实现方法
Aug 08 Python
Python + Flask 实现简单的验证码系统
Oct 01 Python
PyTorch和Keras计算模型参数的例子
Jan 02 Python
python 模拟登陆163邮箱
Dec 15 Python
详解Python的Django框架中的templates设置
May 11 #Python
Python素数检测的方法
May 11 #Python
Python中IPYTHON入门实例
May 11 #Python
Python使用MONGODB入门实例
May 11 #Python
python学习数据结构实例代码
May 11 #Python
Python使用CMD模块更优雅的运行脚本
May 11 #Python
Python中DJANGO简单测试实例
May 11 #Python
You might like
深入array multisort排序原理的详解
2013/06/18 PHP
php查询mysql大量数据造成内存不足的解决方法
2015/03/04 PHP
PHP单例模式详细介绍
2015/07/01 PHP
PHP preg_match实现正则表达式匹配功能【输出是否匹配及匹配值】
2017/07/19 PHP
脚本吧 - 幻宇工作室用到js,超强推荐base.js
2006/12/23 Javascript
js当一个变量为函数时 应该注意的一点细节小结
2011/12/29 Javascript
javascript函数作用域学习示例(js作用域)
2014/01/13 Javascript
jQuery中的height innerHeight outerHeight区别示例介绍
2014/06/15 Javascript
Bootstrap每天必学之下拉菜单
2015/11/25 Javascript
JavaScript 定时器 SetTimeout之定时刷新窗口和关闭窗口(代码超简单)
2016/02/26 Javascript
浅谈window.onbeforeunload() 事件调用ajax
2016/06/29 Javascript
VueJS如何引入css或者less文件的一些坑
2017/04/25 Javascript
Vue.2.0.5实现Class 与 Style 绑定的实例
2017/06/20 Javascript
详解vue.js移动端导航navigationbar的封装
2017/07/05 Javascript
angular1配合gulp和bower的使用教程
2018/01/19 Javascript
使用Vue动态生成form表单的实例代码
2018/04/26 Javascript
谈谈JavaScript令人迷惑的==与+
2020/08/31 Javascript
Python基于smtplib实现异步发送邮件服务
2015/05/28 Python
Python的Django框架中设置日期和字段可选的方法
2015/07/17 Python
Django1.7+python 2.78+pycharm配置mysql数据库
2016/10/09 Python
python实现读取并显示图片的两种方法
2017/01/13 Python
Python PyQt5实现的简易计算器功能示例
2017/08/23 Python
机器学习python实战之决策树
2017/11/01 Python
python3 实现一行输入,空格隔开的示例
2018/11/14 Python
python通过配置文件共享全局变量的实例
2019/01/11 Python
python编写计算器功能
2019/10/25 Python
Python socket处理client连接过程解析
2020/03/18 Python
canvas之万花筒效果的简单实现(推荐)
2016/08/16 HTML / CSS
给定一个时间点,希望得到其他时间点
2013/11/07 面试题
写演讲稿所需要注意的4个条件
2014/01/09 职场文书
三年级学生评语
2014/04/23 职场文书
市级青年文明号申报材料
2014/05/26 职场文书
单位法定代表人授权委托书
2014/09/20 职场文书
2016年艾滋病宣传活动总结
2016/04/01 职场文书
利用Nginx代理如何解决前端跨域问题详析
2021/04/02 Servers
十大最帅动漫男主 碓冰拓海上榜,第一是《灌篮高手》男主角
2022/03/18 日漫