从Python的源码来解析Python下的freeblock
程序员文章站
2022-04-12 09:57:13
1 引言
在python内存管理中,有一个block的概念。它比较类似于sgi次级空间配置器。
首先申请一块大的空间(4kb),然后把它切割成一小份(8, 16 一直到...
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的方式来工作了。
如下图所示:
下一篇: 在CorelDRAW中如何焊接对象?
推荐阅读
-
从源码解析Python的Flask框架中request对象的用法
-
猪肉涨价飞快?让我们用python来预测一下今年最后一个月的猪肉价格吧!
-
使用httplib模块来制作Python下HTTP客户端的方法
-
使用Python实现windows下的抓包与解析
-
在Python下利用OpenCV来旋转图像的教程
-
从入门到放弃:python爬虫系列-xpath解析库的使用
-
从Python的源码浅要剖析Python的内存管理
-
Python调用SQLPlus来操作和解析Oracle数据库的方法
-
初步解析Python下的多进程编程
-
win10下Opencv源码编译支持CUDA加速的Python环境,超级详细教程!