从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实现JAVA源代码从ANSI到UTF-8的批量转换方法
Aug 10 Python
Python实现单词翻译功能
Jun 06 Python
Python实现的文本编辑器功能示例
Jun 30 Python
numpy数组拼接简单示例
Dec 15 Python
python实现将一个数组逆序输出的方法
Jun 25 Python
tensorflow实现加载mnist数据集
Sep 08 Python
Python将字符串常量转化为变量方法总结
Mar 17 Python
python进程和线程用法知识点总结
May 28 Python
Python正则表达式匹配日期与时间的方法
Jul 07 Python
用Python写一个自动木马程序
Sep 17 Python
python 解决flask uwsgi 获取不到全局变量的问题
Dec 22 Python
python cv2图像质量压缩的算法示例
Jun 04 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 处理图片的类实现代码
2009/10/23 PHP
php利用header函数实现文件下载时直接提示保存
2009/11/12 PHP
php 模拟post_验证页面的返回状态(实例讲解)
2013/10/28 PHP
部署PHP项目应该注意的几点事项分享
2013/12/20 PHP
浅谈PHP值mysql操作类
2016/06/29 PHP
JQuery调用WebServices的方法和4个实例
2014/05/06 Javascript
JavaScript实现的encode64加密算法实例分析
2015/04/15 Javascript
由浅入深讲解Javascript继承机制与simple-inheritance源码分析
2015/12/13 Javascript
浅谈jQuery效果函数
2016/09/16 Javascript
AngularJS自定义服务与fliter的混合使用
2016/11/24 Javascript
简单实现bootstrap选项卡效果
2017/02/08 Javascript
NodeJs使用Mysql模块实现事务处理实例
2017/05/31 NodeJs
angular框架实现全选与单选chekbox的自定义
2017/07/06 Javascript
详解angular笔记路由之angular-router
2017/09/12 Javascript
Three.js利用Detector.js插件如何实现兼容性检测详解
2017/09/26 Javascript
使用javaScript实现鼠标拖拽事件
2020/04/03 Javascript
JavaScript实现计算多边形质心的方法示例
2018/01/31 Javascript
React Native自定义控件底部抽屉菜单的示例
2018/02/08 Javascript
基于Webpack4和React hooks搭建项目的方法
2019/02/05 Javascript
ES6字符串的扩展实例
2020/12/21 Javascript
[01:25]2015国际邀请赛最佳短片奖——斧王《拆塔英雄:天赋异禀》
2015/09/22 DOTA
在Mac OS上使用mod_wsgi连接Python与Apache服务器
2015/12/24 Python
浅谈python下含中文字符串正则表达式的编码问题
2018/12/07 Python
python调用staf自动化框架的方法
2018/12/26 Python
Python二叉树的镜像转换实现方法示例
2019/03/06 Python
python3 pygame实现接小球游戏
2019/05/14 Python
pygame实现贪吃蛇游戏(上)
2019/10/29 Python
如何基于Python制作有道翻译小工具
2019/12/16 Python
HTML5 canvas基本绘图之绘制线条
2016/06/27 HTML / CSS
创业女性典型材料
2014/05/02 职场文书
2014年采购员工作总结
2014/11/18 职场文书
小学教师见习总结
2015/06/23 职场文书
欠条范文
2015/07/03 职场文书
乡镇干部学习心得体会
2016/01/23 职场文书
go xorm框架的使用
2021/05/22 Golang
ES6 解构赋值的原理及运用
2021/05/25 Javascript