一、什么是内存

在实际中,实现任何数据结构,都需要使用计算机的内存。

  • 字序列&内存字节
    计算机存储器被组织成序列,其中每一个序列通常包含4、8或者16个字节(取决于计算机)。这一个个的字序列即为一个一个的内存字节
  • 内存地址
    这些内存从0编号到N-1,N是计算机可获得的内存字节的数量。与每个内存字节相关联的数字称为内存地址

一个计算机的存储器基本可被视为一个巨大的内存字节的矩阵。

二、内存堆

在python中,所有对象都存储在内存池中,该内存池称为 内存堆python堆
例如,当执行操作 a = A() 时,A类的一个新实例被创建,并被存储在内存堆的某个地方。
当执行Python程序时,Python解释器会负责协调操作系统空间的使用,并管理内存堆的使用。

三、内存分配

1、相关概念

  • 内存堆存储空间被分成连续的,块的大小可以是变量或固定量。(系统得实现这个功能,才可以迅速为新的对象分配内存。)
  • 空闲表
    系统会将连续空间的可用内存连接到一个链表上,这个表被称为空闲表。
    只要空间的内存未被使用,它们就会被连接到链表中。
  • 碎片
    随着内存的分配与释放,空闲表中的空间集会发生变化,未使用的内存空间被已使用的内存空间分离成了不相连的空间。这些不相连的未使用内存空间,即碎片。
    内部碎片:所分配的内存块里的一部分未使用,即产生了内部碎片
    外部碎片:几个已分配的内存块之间有未使用的内存空间,即产生了外部碎片
2、内存分配

运行时,环境应该以尽量减少外部碎片的方式来分配内存。
常用的方法有

  • 最佳适应算法:搜索整个空闲表,查找其大小最接近所请求内存的空间
  • 首次适应算法:从空闲表的首部开始搜索,直到搜索到第一个足够大的空间
    循环首次适应算法:同首次适应算法,但它每次搜索都从以前中断的地方开始,将空闲表视为循环链表。
  • 最差适应算法:搜索整个空闲表,找到最大的可用内存空间

四、Python解释器使用的额外内存

并非只有在运行Python程序时需要使用内存,python解释器还会使用一些额外的内存。

1、运行时的调用栈
  • 调用栈
    运行中的python程序有一个私有栈,被称为调用栈python解释器栈,该栈用于跟踪函数调用的当前活跃的嵌套序列
  • 活动记录
    调用栈的每个条目都是一个活动记录(或称为框架),存储着函数调用的重要信息

调用栈
调用栈的顶部是正在调用的活动记录,也就是当前控制执行的函数活动。
栈的其余元素是挂起等待调用的活动记录,也就是函数已经调用另一个函数,目前等待另一个函数结束时返回控制给前函数。
(当一个新函数被调用时,调用该函数的活动记录被压入栈。调用结束后,它的活动记录从栈中弹出,Python解释器恢复暂停的调用过程)

活动记录
每个活动记录包含:
代表着函数调用的本地命名空间的字典(命名空间作为参数和局部变量的标识符映射到对象的值,但对象的值驻留在内存堆中);
还包含函数定义本身的引用;
还包含一个特殊变量—程序计数器(包含当前正在执行的函数语句的地址。当一个函数返回控制到另一个函数时,该挂起函数存储的程序计数器使得解释器正确继续该函数的运行)。

以上模式的实现,让我们的程序可以使用递归模式。

2、操作数栈

在如算术表达式((a*b)+(c+d)*e)/f类似的语句中,解释器通过使用操作数栈进行计算。