从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 列表(List)操作方法详解
Mar 11 Python
python如何把嵌套列表转变成普通列表
Mar 20 Python
Pandas 对Dataframe结构排序的实现方法
Apr 10 Python
关于python之字典的嵌套,递归调用方法
Jan 21 Python
Python 微信爬虫完整实例【单线程与多线程】
Jul 06 Python
django 中使用DateTime常用的时间查询方式
Dec 03 Python
解决Tensorflow sess.run导致的内存溢出问题
Feb 05 Python
如何在sublime编辑器中安装python
May 20 Python
基于Python实现2种反转链表方法代码实例
Jul 06 Python
python 星号(*)的多种用途
Sep 21 Python
五种Python转义表示法
Nov 27 Python
Python3.10的一些新特性原理分析
Sep 15 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学习之数据类型之间的转换介绍
2011/06/09 PHP
PHP变量的定义、可变变量、变量引用、销毁方法
2013/12/20 PHP
php计算给定时间之前的函数用法实例
2015/04/03 PHP
php关键字仅替换一次的实现函数
2015/10/29 PHP
Laravel学习教程之路由模块
2017/08/18 PHP
PHP实现简单的模板引擎功能示例
2017/09/02 PHP
PHP实现的服务器一致性hash分布算法示例
2018/08/09 PHP
通过JavaScript使Div居中并随网页大小改变而改变
2013/06/24 Javascript
简单的Jquery遮罩层代码实例
2013/11/14 Javascript
理解jQuery stop()方法
2014/11/21 Javascript
javascript常用代码段搜集
2014/12/04 Javascript
果断收藏9个Javascript代码高亮脚本
2016/01/06 Javascript
如何用angularjs制作一个完整的表格
2016/01/21 Javascript
jquery分页插件jquery.pagination.js实现无刷新分页
2016/04/01 Javascript
jQuery+ajax+asp.net获取Json值的方法
2016/06/08 Javascript
利用Three.js如何实现阴影效果实例代码
2017/09/26 Javascript
微信小程序之判断页面滚动方向的示例代码
2018/08/30 Javascript
HTML+JS实现“代码雨”效果源码(黑客帝国文字下落效果)
2020/03/17 Javascript
10分钟学会js处理json的常用方法
2020/12/06 Javascript
python将txt文件读取为字典的示例
2018/12/22 Python
python 使用plt画图,去除图片四周的白边方法
2019/07/09 Python
python OpenCV GrabCut使用实例解析
2019/11/11 Python
Python的几种主动结束程序方式
2019/11/22 Python
Pycharm和Idea支持的vim插件的方法
2020/02/21 Python
python实现井字棋小游戏
2020/03/04 Python
详解scrapy内置中间件的顺序
2020/09/28 Python
台湾网友喜爱的综合型网路购物商城:Yahoo! 奇摩购物中心
2018/03/10 全球购物
澳大利亚厨房和家用电器购物网站:Bing Lee
2021/01/11 全球购物
是否可以从一个static方法内部发出对非static方法的调用?
2014/08/18 面试题
酒店保安员岗位职责
2014/01/31 职场文书
个人合作协议书范本
2014/04/18 职场文书
爱祖国演讲稿
2014/05/04 职场文书
小学学习雷锋活动总结
2014/07/03 职场文书
合作经营协议书范本
2014/09/16 职场文书
《天净沙·秋思》教学反思三篇
2019/11/02 职场文书
关于python类SortedList详解
2021/09/04 Python