Python源码阅读-内存管理机制(一)

========================== 

基本阅读完了, 只是没时间梳理, 趁着这今天时间比较空

逐步梳理, 发上来……也算是小结下, 要开始准备简历找工作了>_

这篇略长, 带很多图, 所以一分为二


Python的内存管理架构

基本分层

Objects/obmalloc.c源码中, 给了一个分层划分

可以看到

第三层layer 3前面已经介绍过了, 几乎每种常用的数据类型都伴有一套缓冲池机制.

在这里, 我们关注的是layer 2/1

简要介绍下layer 1, 然后重点关注layer 2, 这才是重点

layer 1: PyMem_ API

PyMem_ API是对操作系统内存管理接口进行的封装

查看pymem.h可以看到

然后object.c中, 我们关注实现, 三个实现的函数调用了对应的宏

这些接口都相对简单

好了, 结束, 开始关注layer 2: Python's object allocator


Python 的内存分配策略

先来看Objects/obmalloc.c中的一段注释

Python引入了内存池机制, 用于管理对小块内存的申请和释放

逻辑

整个小块内存池可以视为一个层次结构

block

Python内存的最小单位, 所有block长度都是8字节对齐的

注意这里block只是一个概念, 在源代码中并没有实体存在.

不同类型block, 对应不同内存大小, 这个内存大小的值被称为size class.

不同长度的block

例如

图示:

注意: 这里有个Size class idx, 这个主要为了后面pool中用到

size classsize class index之间的转换

pool

pool管理block, 一个pool管理着一堆有固定大小的内存块

本质: pool管理着一大块内存, 它有一定的策略, 将这块大的内存划分为多个大小一致的小块内存.

pool size

在Python中, 一个pool的大小通常为一个系统内存页. 4kB

pool组成

pool的4kB内存 = pool_header + block集合(N多大小一样的block)

pool_header

pool_header的作用

结构图:

pool初始化

从内存中初始化一个全新的空的pool

Objects/obmalloc.c

初始化后的图

pool进行block分配 – 0 总体代码

总体分配的代码如下

pool进行block分配 – 1 刚开始

内存块尚未分配完, 且此时不存在回收的block, 全新进来的时候, 分配第一块block

所以进入的逻辑是代码-2

结果图示

pool进行block分配 – 2 回收了某几个block

回收涉及的代码

没释放一个block, 该block就会变成 pool->freeblock 的头节点, 而单链表一个节点如何指向下一个节点呢? 通过赋值, 节点内存空间保存着下个节点的地址, 最后一个节点指向NULL(知道上面代码-1的判断条件了吧>_

假设已经连续分配了5块, 第1块和第4块被释放

此时内存图示

此时再一个block分配调用进来, 执行分配, 进入的逻辑是代码-1

pool进行block分配 – 3 pool用完了

pool中内存空间都用完了, 进入代码-3

获取下一个pool(链表上每个pool的block size都是一致的)

好了, pool到此位置, 下篇进入arena

打赏支持我写出更多好文章,谢谢!

打赏作者

打赏支持我写出更多好文章,谢谢!

任选一种支付方式

1 3 收藏 评论

关于作者:wklken

Pythonista/vimer 个人主页 · 我的文章 · 37 ·   

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部