各位用户为了找寻关于从Python的源码来解析Python下的freeblock的资料费劲了很多周折。这里教程网为您整理了关于从Python的源码来解析Python下的freeblock的相关资料,仅供查阅,以下为您介绍关于从Python的源码来解析Python下的freeblock的详细内容
1 引言
在python内存管理中,有一个block的概念。它比较类似于SGI次级空间配置器。 首先申请一块大的空间(4KB),然后把它切割成一小份(8, 16 一直到512)。 当有内存申请的请求时候,简单的流程是:根据大小找到对应的block,然后在freeblock 上给它一份。
2 问题
整个过程是一种比较自然的slab分配方式。但当我读到这段代码时,却感到疑惑:
? 1 2 3 4 5 6 7 8 9static 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。
但是为什么要这么做? 直到看到内存回收的代码:
? 1 2 3 4 5 6 7static void _PyObject_Free(void
*
ctx, void
*
p)
{
...
*
(block
*
*
)p
=
lastfree
=
pool
-
>freeblock;
pool
-
>freeblock
=
(block
*
)p;
...
}
回想一下SGI次级空间配置,它需要一个链表,指向block中可用的小块。因为这些快,是离散的,只有用指针才能索引它。 在SGI次级空间配置中,是用一个union,达到了节省空间的目的:有数据时,它存储着真正的数据;没有数据时,它就变成指向下一块可用内存的指针:
? 1 2 3 4union __Obj {
union __Obj
*
free_list_link;
char client_data[];
};
这样一想,问题就变得很明显了。freeblock指向一个链表,链表的next域就由它自己来索引。 在_PyObject_Free中,内存p是要被回收的,它应该插在freeblock的链表头,freeblock被更新指向它。同时,p指向原来freeblock指向的内容,这是一个很简单的链表插入操作。 这样在遍历的时候,我们就可以用freeblock = * freeblock的方式来工作了。 如下图所示: