从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编程-将Python程序转化为可执行程序[整理]
Apr 09 Python
Python脚本实现自动将数据库备份到 Dropbox
Feb 06 Python
python实现逆序输出一个数字的示例讲解
Jun 25 Python
python opencv实现图片旋转矩形分割
Jul 26 Python
对dataframe数据之间求补集的实例详解
Jan 30 Python
Python分割训练集和测试集的方法示例
Sep 19 Python
python生成器/yield协程/gevent写简单的图片下载器功能示例
Oct 28 Python
pygame实现俄罗斯方块游戏(基础篇2)
Oct 29 Python
Python高级特性之闭包与装饰器实例详解
Nov 19 Python
Tensorflow之梯度裁剪的实现示例
Mar 08 Python
通过自学python能找到工作吗
Jun 21 Python
Python3.9.1中使用split()的处理方法(推荐)
Feb 07 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
phpmyadmin导入(import)文件限制的解决办法
2009/12/11 PHP
图解找出PHP配置文件php.ini的路径的方法
2014/08/20 PHP
php中常量DIRECTORY_SEPARATOR用法深入分析
2014/11/14 PHP
php获取服务器操作系统相关信息的方法
2016/10/08 PHP
基于Laravel 5.2 regex验证的正确写法
2019/09/29 PHP
解决laravel-admin 自己新建页面里 js 需要刷新一次的问题
2019/10/03 PHP
PNGHandler-借助JS让PNG图在IE下实现透明(包括背景图)
2007/08/31 Javascript
jqPlot Option配置对象详解
2009/07/25 Javascript
基于JQuery的浮动DIV显示提示信息并自动隐藏
2011/02/11 Javascript
jQuery 插件仿百度搜索框智能提示(带Value值)
2013/01/22 Javascript
jquery子元素过滤选择器使用示例
2013/06/24 Javascript
jQuery 三击事件实现代码
2013/09/11 Javascript
目前流行的JavaScript库的介绍及对比
2013/09/29 Javascript
JavaScript cookie的设置获取删除详解
2014/02/11 Javascript
js模仿php中strtotime()与date()函数实现方法
2015/08/11 Javascript
JS实现合并两个数组并去除重复项只留一个的方法
2015/12/17 Javascript
全面接触神奇的Bootstrap导航条实战篇
2016/08/01 Javascript
js实现滑动到页面底部自动加载更多功能
2017/02/15 Javascript
深究AngularJS——ng-checked(回写:带真实案例代码)
2017/06/13 Javascript
jquery实现的简单轮播图功能【适合新手】
2018/08/17 jQuery
vue2.0 watch里面的 deep和immediate用法说明
2020/10/30 Javascript
python求pi的方法
2014/10/08 Python
Python解析json文件相关知识学习
2016/03/01 Python
Python数据结构与算法之图的广度优先与深度优先搜索算法示例
2017/12/14 Python
Python使用pymongo模块操作MongoDB的方法示例
2018/07/20 Python
Python实现简单查找最长子串功能示例
2019/02/26 Python
Python统计文本词汇出现次数的实例代码
2020/02/27 Python
python 操作mysql数据中fetchone()和fetchall()方式
2020/05/15 Python
vivo智能手机官方商城:vivo
2016/09/22 全球购物
Quiksilver美国官网:始于1969年的优质冲浪服和滑雪板外套
2020/04/20 全球购物
高级人员简历的自我评价分享
2013/11/03 职场文书
工作失职检讨书(精华篇)
2014/10/15 职场文书
大学生支教感言
2015/08/01 职场文书
导游词之无锡梅园
2019/11/28 职场文书
CSS3实现三角形不断放大效果
2021/04/13 HTML / CSS
使用python将HTML转换为PDF pdfkit包(wkhtmltopdf) 的使用方法
2022/04/21 Python