从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深入学习之对象的属性
Aug 31 Python
Python实现的飞速中文网小说下载脚本
Apr 23 Python
python数据结构之图深度优先和广度优先实例详解
Jul 08 Python
Python如何判断数独是否合法
Sep 08 Python
Python实现批量读取图片并存入mongodb数据库的方法示例
Apr 02 Python
Python之批量创建文件的实例讲解
May 10 Python
tensorflow实现简单的卷积神经网络
May 24 Python
wtfPython—Python中一组有趣微妙的代码【收藏】
Aug 31 Python
简单了解python关系(比较)运算符
Jul 08 Python
C++和python实现阿姆斯特朗数字查找实例代码
Dec 07 Python
python 获取域名到期时间的方法步骤
Feb 10 Python
总结Python使用过程中的bug
Jun 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作的文本留言本的例子(四)
2006/10/09 PHP
PHP表单验证的3个函数ISSET()、empty()、is_numeric()的使用方法
2011/08/22 PHP
PHP读取CURL模拟登录时生成Cookie文件的方法
2014/11/04 PHP
thinkphp数据查询和遍历数组实例
2014/11/28 PHP
WordPress开发中用于标题显示的相关函数使用解析
2016/01/07 PHP
php str_getcsv把字符串解析为数组的实现方法
2017/04/05 PHP
记Laravel调用Gin接口调用formData上传文件的实现方法
2019/12/12 PHP
用js实现下载远程文件并保存在本地的脚本
2008/05/06 Javascript
jQuery提交多个表单的小例子
2013/06/30 Javascript
avalonjs制作响应式瀑布流特效
2015/05/06 Javascript
JQuery EasyUI Layout 在from布局自适应窗口大小的实现方法
2016/05/28 Javascript
js通过keyCode值判断单击键盘上某个键,然后触发指定的事件方法
2017/02/19 Javascript
JavaScript瀑布流布局实现代码
2017/05/06 Javascript
详解使用Vue Router导航钩子与Vuex来实现后退状态保存
2017/09/11 Javascript
Vue父子组件之间的通信实例详解
2018/09/28 Javascript
微信小程序Flex布局用法深入浅出分析
2019/04/25 Javascript
微信小程序实现打开并下载服务器上面的pdf文件到手机
2019/09/20 Javascript
使用vscode快速建立vue模板过程详解
2019/10/10 Javascript
[01:14:30]TNC vs VG 2019国际邀请赛淘汰赛 胜者组赛BO3 第二场 8.20.mp4
2019/08/22 DOTA
Python入门篇之字典
2014/10/17 Python
Python使用爬虫猜密码
2016/02/19 Python
Win7下Python与Tensorflow-CPU版开发环境的安装与配置过程
2018/01/04 Python
Python字符串格式化%s%d%f详解
2018/02/02 Python
Python使用Selenium爬取淘宝异步加载的数据方法
2018/12/17 Python
python自带tkinter库实现棋盘覆盖图形界面
2019/07/17 Python
Python3.7 pyodbc完美配置访问access数据库
2019/10/03 Python
Python标准库:内置函数max(iterable, *[, key, default])说明
2020/04/25 Python
Python 代码调试技巧示例代码
2020/08/11 Python
Python类绑定方法及非绑定方法实例解析
2020/10/09 Python
一套.net面试题及答案
2016/11/02 面试题
销售团队获奖感言
2014/08/14 职场文书
装配车间主任岗位职责
2015/04/08 职场文书
绿色环保倡议书
2015/04/28 职场文书
孙振耀退休感言
2015/08/01 职场文书
JavaScript嵌入百度地图API的最详细方法
2021/04/16 Javascript
python使用tkinter实现透明窗体上绘制随机出现的小球(实例代码)
2021/05/17 Python