从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 结巴分词实现关键词抽取分析
Oct 21 Python
python ansible服务及剧本编写
Dec 29 Python
利用Opencv中Houghline方法实现直线检测
Feb 11 Python
python画折线图的程序
Jul 26 Python
Python3中bytes类型转换为str类型
Sep 27 Python
python实现网页自动签到功能
Jan 21 Python
Python利用itchat库向好友或者公众号发消息的实例
Feb 21 Python
基于python的BP神经网络及异或实现过程解析
Sep 30 Python
Pytorch学习之torch用法----比较操作(Comparison Ops)
Jun 28 Python
pytorch简介
Nov 11 Python
python 获取谷歌浏览器保存的密码
Jan 06 Python
这样写python注释让代码更加的优雅
Jun 02 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 join函数应用
2011/05/04 PHP
WordPress网站性能优化指南
2015/11/18 PHP
php利用imagemagick实现复古老照片效果实例
2017/02/16 PHP
thinkphp 框架数据库切换实现方法分析
2020/05/18 PHP
javascript Ext JS 状态默认存储时间
2009/02/15 Javascript
[原创]IE view-source 无法查看看源码 JavaScript看网页源码
2009/07/19 Javascript
jquery 表格分页等操作实现代码(pagedown,pageup)
2010/04/11 Javascript
裁剪字符串trim()自定义改进版
2013/04/10 Javascript
关于jQuery中的each方法(jQuery到底干了什么)
2014/03/05 Javascript
Bootstrap对话框使用实例讲解
2016/09/24 Javascript
微信小程序之仿微信漂流瓶实例
2016/12/09 Javascript
遍历json获得数据的几种方法小结
2017/01/21 Javascript
Angular.js之作用域scope'@','=','&'实例详解
2017/02/28 Javascript
JavaScript通过改变文字透明度实现的文字闪烁效果实例
2017/04/27 Javascript
详解利用Angular实现多团队模块化SPA开发框架
2017/11/27 Javascript
vue 地图可视化 maptalks 篇实例代码详解
2019/05/21 Javascript
jquery实现动态创建form并提交的方法示例
2019/05/27 jQuery
javascript创建元素和删除元素实例小结
2019/06/19 Javascript
微信小程序 搜索框组件代码实例
2019/09/06 Javascript
javascript实现电商放大镜效果
2020/11/23 Javascript
python中global与nonlocal比较
2014/11/21 Python
Python Web框架Flask中使用新浪SAE云存储实例
2015/02/08 Python
python 将大文件切分为多个小文件的实例
2019/01/14 Python
Python 实现平台类游戏添加跳跃功能
2020/03/27 Python
解决python调用自己文件函数/执行函数找不到包问题
2020/06/01 Python
解决Keras 自定义层时遇到版本的问题
2020/06/16 Python
Python基于tkinter canvas实现图片裁剪功能
2020/11/05 Python
CSS3弹性布局内容对齐(justify-content)属性使用详解
2017/07/31 HTML / CSS
CSS3中的opacity属性使用教程
2015/08/19 HTML / CSS
微信小程序“圣诞帽”的实现思路详解
2017/12/28 HTML / CSS
Cotton On香港网站:澳洲时装连锁品牌
2018/11/01 全球购物
竞聘书格式及范文
2014/03/31 职场文书
企业承诺书格式
2014/05/21 职场文书
2016孝老爱亲模范事迹材料
2016/02/26 职场文书
Pytest allure 命令行参数的使用
2021/04/18 Python
电脑无法安装Windows 11怎么办?无法安装Win11的解决方法
2021/11/21 数码科技