从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 相关文章推荐
Python2.5/2.6实用教程 入门基础篇
Nov 29 Python
Python中字符串的处理技巧分享
Sep 17 Python
对numpy中向量式三目运算符详解
Oct 31 Python
TensorFlow卷积神经网络之使用训练好的模型识别猫狗图片
Mar 14 Python
ERLANG和PYTHON互通实现过程详解
Jul 05 Python
HTML的form表单和django的form表单
Jul 25 Python
如何为Python终端提供持久性历史记录
Sep 03 Python
Python 获取命令行参数内容及参数个数的实例
Dec 20 Python
Pytorch实现各种2d卷积示例
Dec 30 Python
Python使用urllib模块对URL网址中的中文编码与解码实例详解
Feb 18 Python
python下载的库包存放路径
Jul 27 Python
C站最全Python标准库总结,你想要的都在这里
Jul 03 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
javascript如何动态加载表格与动态添加表格行
2013/11/27 Javascript
jquery获取radio值(单选组radio)
2014/10/16 Javascript
浅谈Javascript数组(推荐)
2016/05/17 Javascript
JavaScript判断微信浏览器实例代码
2016/06/13 Javascript
jQuery插件简单学习实例教程
2016/07/01 Javascript
JS数组去掉重复数据只保留一条的实现代码
2016/08/11 Javascript
JavaScript制作简单分页插件
2016/09/11 Javascript
jQuery Form表单取值的方法
2017/01/11 Javascript
原生js实现放大镜特效
2017/03/08 Javascript
利用CDN加速react webpack打包后的文件详解
2018/02/22 Javascript
浅谈node.js 命令行工具(cli)
2018/05/10 Javascript
vue elementui form表单验证的实现
2018/11/11 Javascript
Vue过渡效果之CSS过渡详解(结合transition,animation,animate.css)
2020/02/05 Javascript
Python Paramiko模块的使用实际案例
2018/02/01 Python
python 批量修改/替换数据的实例
2018/07/25 Python
Python迭代器与生成器基本用法分析
2018/07/26 Python
Python二叉树的镜像转换实现方法示例
2019/03/06 Python
pyqt 实现为长内容添加滑轮 scrollArea
2019/06/19 Python
Biblibili视频投稿接口分析并以Python实现自动投稿功能
2021/02/05 Python
CSS3实现粒子旋转伸缩加载动画
2016/04/22 HTML / CSS
HTML5实现Notification API桌面通知功能
2016/03/02 HTML / CSS
神话般的珠宝:Ross-Simons
2020/07/13 全球购物
外语系毕业生找工作的求职信
2013/11/28 职场文书
2014年应届大学生毕业自我鉴定
2014/01/31 职场文书
数控专业自荐书范文
2014/03/16 职场文书
个人担保书范文
2014/05/20 职场文书
商务英语专业毕业生求职信
2014/07/06 职场文书
2014年艾滋病防治工作总结
2014/12/10 职场文书
异地恋情人节寄语
2015/02/28 职场文书
端午节寄语2015
2015/03/23 职场文书
合同纠纷调解书
2015/05/20 职场文书
亲情作文之母爱
2019/09/25 职场文书
Python机器学习之基础概述
2021/05/19 Python
详解JSON.parse和JSON.stringify用法
2022/02/18 Javascript
HTML中的表单元素介绍
2022/02/28 HTML / CSS
Python如何快速找到多个字典中的公共键(key)
2022/04/29 Python