从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 相关文章推荐
Flask框架学习笔记(一)安装篇(windows安装与centos安装)
Jun 25 Python
python 定义n个变量方法 (变量声明自动化)
Nov 10 Python
对python捕获ctrl+c手工中断程序的两种方法详解
Dec 26 Python
Python 支付整合开发包的实现
Jan 23 Python
python pyinstaller 加载ui路径方法
Jun 10 Python
Python之Numpy的超实用基础详细教程
Oct 23 Python
Python中类似于jquery的pyquery库用法分析
Dec 02 Python
python解析多层json操作示例
Dec 30 Python
使用python实现多维数据降维操作
Feb 24 Python
Matplotlib.pyplot 三维绘图的实现示例
Jul 28 Python
python性能测试工具locust的使用
Dec 28 Python
使用pandas读取表格数据并进行单行数据拼接的详细教程
Mar 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
转生史莱姆:萌王第一次撸串开心到飞起,哥布塔撸串却神似界王神
2018/11/30 日漫
全国FM电台频率大全 - 27 陕西省
2020/03/11 无线电
php下用GD生成生成缩略图的两个选择和区别
2007/04/17 PHP
php中理解print EOT分界符和echo EOT的用法区别小结
2010/02/21 PHP
Thinkphp自定义生成缩略图尺寸的方法
2019/08/05 PHP
QQ空间顶部折页撕开效果示例代码
2014/06/15 Javascript
通过JS动态创建一个html DOM元素并显示
2014/10/15 Javascript
jquery获取checkbox的值并post提交
2015/01/14 Javascript
jQuery+html5+css3实现圆角无刷新表单带输入验证功能代码
2015/08/21 Javascript
js强制把网址设为默认首页
2015/09/29 Javascript
基于Bootstrap里面的Button dropdown打造自定义select
2016/05/30 Javascript
AngularJS中的表单简单入门
2016/07/28 Javascript
Angular指令之restict匹配模式的详解
2017/07/27 Javascript
使用Bootstrap和Vue实现用户信息的编辑删除功能
2017/10/25 Javascript
使用webpack打包koa2 框架app
2018/02/02 Javascript
详解vue中点击空白处隐藏div的实现(用指令实现)
2018/04/19 Javascript
发布一款npm包帮助理解npm的使用
2019/01/03 Javascript
详解Vue前端对axios的封装和使用
2019/04/01 Javascript
Vue 解决父组件跳转子路由后当前导航active样式消失问题
2020/07/21 Javascript
VUE 单页面使用 echart 窗口变化时的用法
2020/07/30 Javascript
[01:57]2018DOTA2亚洲邀请赛赛前采访-iG
2018/04/03 DOTA
python 参数列表中的self 显式不等于冗余
2008/12/01 Python
python爬虫之百度API调用方法
2017/06/11 Python
python根据unicode判断语言类型实例代码
2018/01/17 Python
Python3实现的Mysql数据库操作封装类
2018/06/06 Python
python 顺时针打印矩阵的超简洁代码
2018/11/14 Python
使用python实现unix2dos和dos2unix命令的例子
2019/08/13 Python
Python3.7 pyodbc完美配置访问access数据库
2019/10/03 Python
html5实现完美兼容各大浏览器的播放器
2014/12/26 HTML / CSS
新员工入职感言
2014/02/01 职场文书
渡河少年教学反思
2014/02/12 职场文书
篮球赛口号
2014/06/18 职场文书
认错检讨书
2014/10/02 职场文书
2015年技术工作总结范文
2015/04/20 职场文书
圆明园纪录片观后感
2015/06/03 职场文书
openGauss数据库JDBC环境连接配置的详细过程(Eclipse)
2022/06/01 Java/Android