Python中的内存管理机制
Python是如何进行内存管理的
python引用了一个内存池(memory pool)机制,即pymalloc机制,用于管理对小块内存的申请和释放
1.介绍
python和其他高级语言一样,会进行自动的内存管理。它使用引用计数机制检测为对象分配的内存是否可以被释放。然后,在Python中内存永远不会返还给操作系统,Python会持有这些内存并在需要时重新使用它们。在很多场景下,这个特性可以减少内存申请和释放所带来的性能损耗;但对于需要长时间运行的Python进程来讲,Python将会占用大量的内存。如果进程使用内存的峰值远大于平均值,这将会造成内存的浪费从而影响本进程甚至是系统中其他进程的性能。
2.Pymalloc
Python使用pymalloc管理内存。在Python中,会频繁的创建和删除很多小对象,如果这些对象的内存申请和释放都使用malloc()和free(),将会带来严重的性能问题。因此,pymalloc分配一系列256KB内存块,称之为arena。每个arena分割为4KB大小的内存池Pool,每个Pool在切分为固定大小的Block。在内存分配时,分配给进程的就是这些Blocks。


3.内存分配


上图中展示了一个usedpool数组,此数组按内存大小组织,每个大小对应一个pool链表,每个pool链表中有多个空闲的Block。在分配内存时,Pymalloc先判断是否存在要申请的大小的pool,如果存在的话,直接从pool中获取一个free Block返回给应用程序,这个过程非常迅速。如果分配完这个Block后此pool变为一个空pool,则将这个Pool从链表中移除。
如果在usedpool中找不到大小匹配的pool,需要在freepool中查找可用的pool。在找不到的情况下,首先会尝试在最后一个arena中是否存在可用的内存,如果有的话则分配一个非freepool使用;如果不存在这样的arena,将会通过malloc()分配一个新的arena。在freepool中找到一个可用的Pool后,会将此Pool切分为固定大小的Pool并加入到userdpool中,并在其中分配一个Free Block应用程序。
4.内存释放

在应用程序要释放一个Block时,过程和分配的过程比较相似。首先会根据Block找到此Block所归属的ool,然后将此Block加入到Pool的Free Block列表中。如果Pool当前是空的,还会将这个Pool加入到usedpool的链表中。如果在Block加入到Free Block后所有的Block都是Free的,会将此Pool从usedpool移动到freepool中

上面的过程可以看到,内存释放的过程基本就是内存申请的反过程,但唯一的区别是缺少了将freepool反换费arena,并将arena通过free()返还给操作系统的步骤。
5.基本数据类型的内存分配
Python中有一小部分的对象是不使用pymalloc进程内存分配的,主要是integer/float/list/dict。为了提升这些常用对象的内存使用效率,这些对象是保存在单独的列表中的。
Python通过malloc()为Integer/Floal两种类型分配大约1KB大小的内存块列表,这些列表被当做Integer/Float的数组使用,而不是使用Pymalloc的分配的8字节的整数倍大小的Block,以减少内存消耗。在创建一个新的Integer/Float对象时,字直接从这个内存列表中获取数据,或是重新分配一块新的Block;在释放时对应的Block重新加入到列表中。这些Block也是不会被返还给操作系统的。
Python为list/dict采用不同的策略,会最多保留80个空闲的list/dict,如果多余80个,多出的会被释放
Python中的内存管理机制的更多相关文章
- Android中的内存管理机制以及正确的使用方式
概述 从操作系统的角度来说,内存就是一块数据存储区域,属于可被操作系统调度的资源.现代多任务(进程)的操作系统中,内存管理尤为重要,操作系统需要为每一个进程合理的分配内存资源,所以可以从两方面来理解操 ...
- Python 中的内存管理
Python 中一切皆对象,这些对象的内存都是在运行时动态地在堆中进行分配的,就连 Python 虚拟机使用的栈也是在堆上模拟的.既然一切皆对象,那么在 Python 程序运行过程中对象的创建和释放就 ...
- cocos2dx中的内存管理机制及引用计数
1.内存管理的两大策略: 谁申请,谁释放原则(类似于,谁污染了内存,最后由谁来清理内存)--------->适用于过程性函数 引用计数原则(创建时,引用数为1,每引用一次,计数加1,调用结束时, ...
- python中的内存管理
不像大多数编译型语言,变量必须在使用之前声明名字和类型,在python中,变量在第一次被赋值时自动声明.在变量创建时,python解释器会根据语法和右侧的操作数来决定新对象的类型,在对象创建后,一个该 ...
- 20191125:Python中的上下文管理机制with
20191125:with上下文管理 with是一个上下文管理器,用于执行代码块所需要的运行的时候的上下文入口和出口.上下文管理器的典型用法包括保存和还原各种全局状态,锁定和解锁资源,关闭打开的文件等 ...
- 【python测试开发栈】—python内存管理机制(二)—垃圾回收
在上一篇文章中(python 内存管理机制-引用计数)中,我们介绍了python内存管理机制中的引用计数,python正是通过它来有效的管理内存.今天来介绍python的垃圾回收,其主要策略是引用计数 ...
- IOS中内存管理机制浅解
我们知道在程序运行过程中要创建大量的对象,和其他高级语言类似,在ObjC中对象时存储在堆中的,系统并不会自动释放堆中的内存(注意基本类型是 由系统自己管理的,放在栈上).如果一个对象创建并使用后没有得 ...
- C++中的内存管理
在C++中也是少不了对内存的管理,在C++中只要有new的地方,在写代码的时候都要想着delete. new分配的时堆内存,在函数结束的时候不会自动释放,如果不delete我分配的堆内存,则会造成内存 ...
- Cocos2d-x开发中C++内存管理
由于开始并没有介绍C++语言,C++的内存管理当然也没进行任何的说明,为了掌握Cocos2d-x中的内存管理机制,是有必要先了解一些C++内存管理的知识.C++内存管理非常复杂,如果完全地系统地介绍可 ...
随机推荐
- Visual studio 正在从以下位置加载符号:Microsoft符号服务器 尝试取消禁用后续符号加载
正在从以下位置加载符号:Microsoft符号服务器 尝试取消禁用后续符号加载 进入VS---工具---选项----调试----符号,看右边有个“Microsoft符号服务器”,将前面的勾去掉,( ...
- PAT 甲级 1053 Path of Equal Weight (30 分)(dfs,vector内元素排序,有一小坑点)
1053 Path of Equal Weight (30 分) Given a non-empty tree with root R, and with weight Wi assigne ...
- jQuery学习四——效果
1.显示,隐藏: <!DOCTYPE html> <html> <head> <title>jquery事件</title> </he ...
- 【搬运】Visual Studio vs2017 vs2019 中文离线安装包下载,替代ISO镜像
原文地址[侵删]:https://blog.csdn.net/fromfire2/article/details/81104648 以下为搬运内容: 官档地址 https://docs.microso ...
- eNSP——ACL基础设置
原理: 实验案例: 拓补图: 实验编址: 1.基础设置 根据实验编址进行基础设置,并检测直连链路的连通性. 2.搭建OSPF网络 在所有路由器运行OSPF协议,通告相应网段到区域0. 在上一个随笔有详 ...
- python变量 - python基础入门(6)
何为python变量,即数据类型.python变量一共六种类型:整数/浮点数/字符串/BOOL/列表/元组/字典,今天先讲解前四种,后三种留到后面的文章在讲解. 首先讲解print() 函数,prin ...
- [学习笔记] Blender layout 视图切换
layout 数字键5 --- 正交视图/透视图 切换 数字键0 -- 摄像机视图 数字键7 -- 顶视图 数字键1 --- 前视图 数字键3 --- 右视图 ctrl +数字键3 --- 左视图 ...
- [转载]Oracle中TO_NUMBER()函数的用法
1 用法简介TO_NUMBER函数()是Oracle中常用的类型转换函数之一,主要是将字符串转换为数值型的格式,与TO_CHAR()函数的作用正好相反. To_number函数的格式如下: To_nu ...
- java连接zookeeper实现zookeeper的基本操作
Java服务端连接Zookeeper,进行节点信息的获取,管理…,整理成一个基本工具, 添加依赖: <dependency> <groupId>org.apache.zooke ...
- Feeding Time 【bfs求最大连通块】
题目链接:https://ac.nowcoder.com/acm/contest/1870/J 题目大意:求最大的连通块是多大 主要是为了防止自己忘记bfs怎么写..... #include<s ...