python的内存分析和处理

这篇文章写得太好了,记录一下:

引自:https://www.jianshu.com/p/2f98dd213f04

2.内存分析和处理
程序的运行离不开对内存的操作,一个软件要运行,须将数据加载到内存中,通过CPU进行内存数据的读写,完
成数据的运算。
2.1 程序内存浅析
软件的程序在计算机中的执行,主要是通过数据单元、控制单元、执行单元共同协作,完成数据的交互达到程序处理数据的目的,在软件的执行过程中,由于系统内存和CPU的资源有限,所以有效的分解软件中的各项数据,将不同的数据加载到不同的内存部分以有效的运行程序,同时可以达到在一个计算机中有效运行更多软件的目的。
栈内存区【stack】:用于直接分配数据,存取数度较快,数据存储不稳定,适用于小数据块的快速存取,一般在程序中用于存储变量数据。
方法区【data】:主要用于加载程序中的代码数据、二进制数据、方法数据等等程序运行需要的预加载数据
静态区【static】:主要用于加载存储程序中的一些静态数据、常量数据等等,在PYTHON中的不可变数据类型的数据也会存储在静态常量区内存中
堆内存【heap】:存储数据稳定持久,一般用于存储加载较为重量级的数据,如程序运行过程中的对象都是存在堆内存中的

内存分析1.png

内存分析2.png

2.1.1. 不可变类型VS可变类型
一般的基本数据类型都是不可变类型,一般的组合数据类型或者自定义数据类型都是可变数据类型
python中的一切都是对象,可以通过id()函数查询对象在内存中的地址数据,可变类型是在定义过数据类型之后,修改
变量的数据,内存地址不会发生变化,不可变数据类型是在定义了数据之后,修改变量的数据,变量不会修改原来
内存地址的数据而是会指向新地址,原有的数据保留,这样更加方便程序中基本数据的利用率。

# # 思考题:
# nums = [12, 13, 15, 18, 20, "hello", ["world", "python"]]

# a = 20  #  nums[4] 是否同一个内存地址? 是!
# print(id(a), id(nums[4]))

# b = "hello"# nums[5] 是否同一个内存地址?
# print(id(b), id(nums[5]))

# c = ["world", "python"] # nums[6] 是否同一个内存地址
# print(id(c), id(nums[6]))

# print(id(nums[6][0]), id(c[0])) # 两个列表中的world字符串

# 奇怪的语法
# if [1][0]:
#     print("hello")
# else:
#     print("world")

数据类型
可变类型:对象在内存地址中存储的数据可变
不可变类型:对象在内存地址中存储的数据不能变化

1. 可变类型

a = list() # 堆内存中:存在一个对象 list(),一个变量a指向这个对象
print(id(a)) # 查看对象a的内存
print(a)

a.append("hello")
print(id(a))
print(a)

print("-----------------------")

2. 不可变类型

不可变类型,在同一个代码块中进行多次使用时会将该类型的对象,直接创建在常量区,在任意引用时候的时候直接赋值内存地址因为不可变类型的对象数据不会发生变化,所以内存中存储一份即可!优化程序执行效率一般情况下,可变类型的对象会创建在堆内存中;不可变类型的对象会创建在常量区内存中

整数类型:-5~256:在解释器加载时,已经自动分配了这些数字的内存
超出-5~256范围的整数,在一个代码块中申请一次内存
交互模式:一行命令就是一个代码块
IDE模式~工具开发:一个模块就是一个代码块

2.1.2代码和代码块
python中的最小运行单元是代码块,代码块的最小单元是一行代码,需要注意的是在交互模式下,每行命令都是一个独立的代码块,每个代码块都会独立的申请一次内存。-5 ~ 256之间的数据自动缓存,字符串自动缓存,超出范围的数据重新申请内存

2.2程序内存代码检测

面试题


内存检测模块:memory profiler
    pip install memory_profiler
测试内存:
    在测试函数前面,添加一个检测注解@profile
‘‘‘
from memory_profile import profile
@profile
def chg_nums(n):
    n = 20
def chg_list(l):
    l.append(20)
a = 18
chg_nums(a)
b = [1,2]
chg_list(b)
print(a) # ?18        20                18             20
print(b) # ?[1,2]     [1,2,20]          [1,2,20]       [1,2]

2.3.操作符号:is和==的使用

跟对象内存相关的三个操作符号:

  1. a is b:判断两个变量a/b,他们指向的对象是否同一个对象
  2. a == b:判断两个变量a/b,他们指向的对象的数据内容是否一致【不做深层判断】
  3. isinstance(a, b) 判断a对象是否属于b类型

新的问题1:如果两个变量,要指向同一个对象?应该怎么操作
例:a = 1000, b = c = a 就能实现多个变量指向同一个对象。

新的问题2:如果有一个对象,我想复制一个单独的对象,应该怎办?

2.4引用、浅拷贝、深拷贝

2.4.1.对象的浅拷贝
对象的浅拷贝指的是,对对象的一种临时备份,浅拷贝的核心机制是主要对赋值对象的内部数据的引用。浅拷贝复制对象的属性值会随着其他拷贝对象对数据改变而改变
2.4.2.对象的深拷贝
对象的深拷贝:拷贝创建一个新对象,同时拷贝对象属性的数据[而不是引用],

2.5.垃圾回收机制

垃圾回收机制:是现阶段任何高级语言的特性!
针对程序运行过程中,出现的垃圾数据进行自动回收
自动回收无效对象数据,通过垃圾回收算法进行操作
垃圾回收:Garbage Collection : GC
遵循垃圾回收算法
PYTHON中,以 引用计数垃圾回收算法 为主要回收机制!
以 标记-清除 和 分代回收 为辅助回收机制!完成PYTHON程序的垃圾回收操作!

2.5.1.引用计数
引用计数算法的原理:python中所有的对象/类型,都是直接或者间接
继承自object对象;问题:谁是object对象

object对象底层是C的一个结构体
typedef struct_object {
int:ob_refcnt,
struct_typeobject *obj_type
} PyObject;

引用计数回收机制:伟大的机制,但是同时存在很大的问题
对象内聚:对象的循环引用

2.5.2标记清除
循环引用的出现,造成了引用计数算法的重大BUG
出现了第二种辅助垃圾回收算法

  1. 标记-清除
    参考画图
    2.5.3分代回收
  2. 分代回收-对于引用计数和标记回收的优化
    三种回收机制共同协作,实现了PYTHON非常高处理效率的垃圾回收机制

作者:我爱python_
链接:https://www.jianshu.com/p/2f98dd213f04
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

原文地址:https://www.cnblogs.com/linwenbin/p/12172645.html

时间: 2024-11-10 00:07:05

python的内存分析和处理的相关文章

『Python』内存分析_list和array的内存增长模式

『Python』内存分析_List对象内存占用分析 在Python中,列表是一个动态的指针数组,而array模块所提供的array对象则是保存相同类型的数值的动态数组.由于array直接保存值,因此它所使用的内存比列表少.列表和array都是动态数组,因此往其中添加新元素,而没有空间保存新的元素时,它们会自动重新分配内存块,并将原来的内存中的值复制到新的内存块中.为了减少重新分配内存的次数,通常每次重新分配时,大小都为原来的k倍.k值越大,则重新分配内存的次数越少,但浪费的空间越多.本节通过一系

『Python』内存分析_List对象内存占用分析

『Python』内存分析_下_list和array的内存增长模式 list声明后结构大体分为3部分,变量名称--list对象(结构性数据+指针数组)--list内容,其中id表示的是list对象的位置, v引用变量名称,v[:]引用list对象,此规则对python其他序列结构也成立,以下示范可用id佐证, a=b时,a和b指向同一个list对象 a=b[:]时,a的list对象和b的list对象指向同一个list内容 Q1:元素存储地址是否连续 首先见得的测试一下list对象存储的内容(结构3

python源码分析----内存分配(1)

上面的一篇粗略的介绍了一下python的对象结构,这篇来分析一个非常重要的部分,内存分配... 好像自己看的源代码,只要是跟C语言相关的,都在内存处理方面做了相当多的工作....例如nginx,它也有实现自己的pool,python当然也不例外.... python在内存分配上面分成了4个层次吧... _____   ______   ______       ________ [ int ] [ dict ] [ list ] ... [ string ]       Python core

(一)Python入门-5函数:01函数的基本概念-内存分析-函数的分类-定义和调用

一:函数介绍 函数是可重用的程序代码块.函数的作用,不仅可以实现代码的复用,更能实现代码的 一致性.一致性指的是,只要修改函数的代码,则所有调用该函数的地方都能得到体现. 在编写函数时,函数体中的代码写法和我们前面讲述的基本一致,只是对代码实现了封 装,并增加了函数调用.传递参数.返回计算结果等内容. 函数基本概念: 1. 一个程序由一个个任务组成:函数就是代表一个任务或者一个功能. 2. 函数是代码复用的通用机制. 二:Python函数的分类 Python中函数分为如下几类: 1. 内置函数

python源码分析----内存分配(2)

早就应该写部分的内容了....最近比较负能量...伤不起啊.. 上一篇说到了,在python的内存分配中两个非常重要的方法:PyObject_Malloc和PyObject_Free 在具体的来这两个方法之前,先要看看别的一些东西 //这里用usedpool构成了一个双向链表 //只用了两个指针就搞定了..我擦... //这里将保存的地址减去了两个指针的大小,那么根据pool结构体的定义,那么将地址加上两个指针,正好就是next,加上3个指针正好就是prev //比较的巧妙 #define PT

python基础(内存分析,不引入第三方变量的方式交换变量的值)

a,b指向同一块内存地址 下面方法是重新给b赋值;a,b指向不同的内存地址 字符串或int类型内存分析 不引入第三方变量的方式,交换a,b的值 原文地址:https://www.cnblogs.com/jingw/p/9188511.html

《python解释器源码剖析》第17章--python的内存管理与垃圾回收

17.0 序 内存管理,对于python这样的动态语言是至关重要的一部分,它在很大程度上决定了python的执行效率,因为在python的运行中会创建和销毁大量的对象,这些都设计内存的管理.同理python还提供了了内存的垃圾回收(GC,garbage collection),将开发者从繁琐的手动维护内存的工作中解放出来.这一章我们就来分析python的GC是如何实现的. 17.1 内存管理架构 在python中内存管理机制是分层次的,我们可以看成有四层,0 1 2 3.在最底层,也就是第0层是

redis内存分析

redis内存分析和清理 web项目中经常会使用redis作为缓存,当项目了运行一段时间后,由于不恰当的使用方法和需求迭代频繁,导致redis内存快速增长,这时就需要对redis的key进行分析,删掉无用的key以节省空间 使用redis自带的命令查看 使用redis自带的info keyspace命令可以查看简略的key分布情况 使用rdbtools工具分析 rdbtools是用python开发的第三方工具,主要作用有: 1.生成csv分析报告 rdb -c memory dump.rdb >

python 进程内存增长问题, 解决方法和工具

python 进程内存增长问题, 解决方法和工具 表现 解决方法 定位问题过程 gdb-python: 搞清楚python程序在做什么 准备gdb 接入gdb 查看线程 查看调用栈 coredump 其他命令 pyrasite: 连接进入python程序 psutil 查看python进程状态 guppy 取得内存使用的各种对象占用情况 无法回收的对象 不可回收对象的例子 ?? objgraph 查找循环引用 表现 运行环境: # uname -a Linux ** 3.10.0-327.el7