从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使用py2exe打包程序介绍
Nov 20 Python
Python连接phoenix的方法示例
Sep 29 Python
python 用正则表达式筛选文本信息的实例
Jun 05 Python
Python利用ORM控制MongoDB(MongoEngine)的步骤全纪录
Sep 13 Python
Python实现删除排序数组中重复项的两种方法示例
Jan 31 Python
django 单表操作实例详解
Jul 30 Python
Python的bit_length函数来二进制的位数方法
Aug 27 Python
python关于调用函数外的变量实例
Dec 26 Python
python开发入门——列表生成式
Sep 03 Python
Python的信号库Blinker用法详解
Dec 31 Python
教你使用TensorFlow2识别验证码
Jun 11 Python
如何利用Python实现n*n螺旋矩阵
Jan 18 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
php setcookie函数的参数说明及其用法
2014/04/20 PHP
PHP的fsockopen、pfsockopen函数被主机商禁用的解决办法
2014/07/08 PHP
开启PHP的伪静态模式
2015/12/31 PHP
Symfony2实现在controller中获取url的方法
2016/03/18 PHP
php实现基于openssl的加密解密方法
2016/09/30 PHP
解决laravel中日志权限莫名变成了root的问题
2019/10/17 PHP
jQuery Div中加载其他页面的实现代码
2009/02/27 Javascript
在线编辑器中换行与内容自动提取
2009/04/24 Javascript
屏蔽相应键盘按钮操作
2014/03/10 Javascript
动态显示可输入的字数提示还可以输入的字数
2014/04/01 Javascript
JS动态修改iframe内嵌网页地址的方法
2015/04/01 Javascript
angularjs自定义ng-model标签的属性
2016/01/21 Javascript
JavaScript实现九九乘法表的简单实例
2016/06/07 Javascript
jQuery 获取select选中值及清除选中状态
2016/12/13 Javascript
JS实现json对象数组按对象属性排序操作示例
2018/05/18 Javascript
从零学Python之入门(四)运算
2014/05/27 Python
python中执行shell命令的几个方法小结
2014/09/18 Python
详解使用 pyenv 管理多个版本 python 环境
2017/10/19 Python
利用Tkinter和matplotlib两种方式画饼状图的实例
2017/11/06 Python
python+django+sql学生信息管理后台开发
2018/01/11 Python
Python中elasticsearch插入和更新数据的实现方法
2018/04/01 Python
Python多线程:主线程等待所有子线程结束代码
2020/04/25 Python
Python 下载Bing壁纸的示例
2020/09/29 Python
基于Python实现粒子滤波效果
2020/12/01 Python
CSS3之transition实现下划线的示例代码
2018/05/30 HTML / CSS
HomeAway的巴西品牌:Alugue Temporada
2018/04/10 全球购物
智能电子秤、手表和健康监测仪:Withings(之前为诺基亚健康)
2018/10/30 全球购物
英国网上自行车商店:Tredz Bikes
2019/10/29 全球购物
法学毕业生自荐信
2013/11/13 职场文书
中专毕业生自我鉴定
2013/11/21 职场文书
教师四风问题整改措施
2014/09/25 职场文书
创先争优宣传标语
2014/10/08 职场文书
出差报告范文
2014/11/06 职场文书
三方协议书
2015/01/27 职场文书
蓬莱阁导游词
2015/02/04 职场文书
2015年秋季运动会加油稿
2015/07/22 职场文书