python 定义空数组_python内存管理机制

这篇文章描述python最新开发版(3.9.0a0)的内存管理机制,如果大家对GC回收感兴趣,也可以持续关注本人,后续将出相关的文章。

大家都知道在python中一切皆对象,其实这描述存在一定的问题,因为python是用c语言编写的,所谓的“对象”其实是用结构体来定义的,咱们暂且不去纠结这些刻板的问题。python中一些对象的定义将会依赖其他对象的定义。由于python具有动态语言这个特性,经常会分配一些内存占用非常少的对象。为了提高内存操作的效率和减少内存碎片,python底层开发了一套通用的内存管理机制,称为PyMalloc。

在讲解之前先看一下内存架构,让大家有宏观的印象。如下图所示:

71ea095a4860a17bbccea49d06c68f53.png

为了印证我不是在这里卖弄,咱们可以在源代码中找找证据。

cf17c516481ac796c05f9a8711399ed1.png

python对大内存(512字节为分界线)和小内存的处理方式就分道扬镳了。对于大内存python使用C Library标准库函数malloc去处理,对于小内存python开发的一套专门管理、分配内存的机制去处理。小内存管理分为三层,arena(区域),pool(池)和block(块)。

让我们从最下的block(块)开始讲起。

block(块)在内存中的大小是确定的,每个block(块)只能容纳一个python对象。block(块)的大小从8个字节到512个字节不等,但是必须是8字节的倍数。如下图所示:

12546830abc68e132f3a613febff3986.png

pool(池)是指由一系列相同大小block(块)构成的集合。通常情况下pool(池)的大小是一个内存页(4kb),限制pool(池)的大小有助于减少碎片化。如果一个python对象被销毁了,内存管理器会用一个同样大小的对象填充这片区域。

每一个pool(池)都会有一个特殊的结构体头,如下图所示:

23d4eb77d6c09a74897353610aff19cc.png

从上面代码可以看出,相同大小的pool(池)通过双向链表(nextpool和prepool字段)。szidx字段保存pool(池)分类索引。ref.count保存的是当前pool(池)中block(块)的已使用数量。arenaindex字段保存pool(池)在arena(区域)中的索引号。

freeblock的描述如下:

所以,一个不含有python对象的block(块)储存另外一个block(块)的地址,这个技巧节省了大量的内存和计算量。

每个pool(池)有3中状态:

  • 已使用 部分使用,既不空也不满。
  • 满 所有pool(池)中的block都已分配。
  • 空 pool(池)中的block(块)都未被分配。

为了有效的管理pool(池)python定义了一个全局数组usedpools。它储存了分类的pool(池)对象指针。正如我们所知所有的大小相同的pool(池)对象链接在一起。为了迭代,我们必须知道链表的头。如果在usedpools中没有当前尺寸的pool(池),将会在内存中新申请。

db143190bc11d54a3404b92ec3b1a5f3.png

需要注意的是pool(池)和block(块)不会从内存中直接分配,而是从已分配的arenas(区域)中直接分配。

arena是指在堆上分配的一个(可分配64个pool(池))256kb大小的内存。

e9f045f95fa989af275410969b8c2947.png

arena(区域)的结构如下所示:

01d804a2be17181152a9702cf88e4143.png

到此,小对象内存管理的大致脉络想必大家应该就清楚了吧。

最后讲讲内存销毁。

Python小对象管理器很少将内存直接使用完返回给操作系统。

如果所有的pool(池)为空,arena(区域)将会全部释放内存。这种情况会发生在在短期内分配了大量的临时对象。而由于这种内存管理机制,python进程中也会有一部分并未使用的内存。

大家还可以使用sys._debugmallocstats()对已使用的内存进行统计。

如果大家任何疑惑,欢迎跟我交流。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值