内存占用
Sayings:
最近被线上程序内存泄漏的问题搞的挺头大(程序在运行中内存占用不断的扩大),便开始看python内存垃圾回收机制、弱引用、循环引用相关的文章,着重查了一下自己的程序是不是真的有循环引用;在看的过程中写了一些demo去验证一些猜想;开篇先问三个问题
- Linux与Windows内存回收机制是不是不同?都是如何实现的
- Linux上不同Python版本内存释放方式是不是不同?不同的版本都更新了那些东西导致差别如此之大
- 最重要的Python3.5中的100M做啥用了?难道是内存池占用?
长期更新中....
本文代码(main.py):
#!/usr/bin/env python # -*- coding:utf-8 -*- import uuid import time class Student(): def __init__(self, stuid): self.stuid = stuid class Class(): def __init__(self, classid): self.classid = classid self.student = Student(uuid.uuid1()) if __name__ == '__main__': li = [] for i in range(500000): li.append(Class(uuid.uuid1())) print('create instance') time.sleep(10) li[:] = [] print('release instance') while True: time.sleep(100)
Linux环境(centos7):
环境:系统初始状态内存占用详情【175M/978M】
1、使用Python3.5.2执行main.py文件,内存峰值占用【556M/978M】,程序使用384M
程序等待10后,打印到‘release instance’字符串,此时内存占用【282M/978M】,程序还占用102M
理论上,li列表都已经清空,所有的class实例引用计数都应该为0,内存应该全部释放才对,但是事实却是有100M内存空间还在占用;假如把demo中循环次数加倍,那最后的内存占用也是相应扩大的;如果我们开发的程序有用到类似这种方式的话,随着使用的时间越长,生成的实例越来越多,即使我们把实例删除,计数清0,内存占用也是越来越大的,最终会导致内存占满,程序崩溃;把程序杀死之后,内存占用又回到最初的状态
那么问题是,那100M为什么没被释放?
2、当我迟迟不能理解的时候,换了一种思路,尝试更换一下Python版本试试,会不会有不一样的状况发生;更改版本为Python3.6.2执行main.py文件,内存峰值占用【559M/978M】,与Python3.5.2基本一致
程序等待10后,打印到‘release instance’字符串时,奇迹发生此时内存占用【183M/978M】,程序占用10M(符合预期)左右,内存几乎全部释放
可以想到Python3.6.2相对于Python3.5.2肯定对内存管理进行了更新, 那么更新了什么导致差别如此的大?
3、使用Python2.7.5执行相同代码时,更为奇葩的事情发生了,内存占用更大,而且最后内存几乎没有进行释放!
内存峰值占用【880M/978M】,程序使用723M
程序等待10后,打印到‘release instance’字符串时,内存占用【822M/978M】,程序使用648M,只释放了70M左右;
Windows环境(w10):
1、在pycharm上执行使用Python3.5.2执行main.py文件,程序峰值占用内存为381M
等待10后,打印到‘release instance’字符串时,内存占用8M,内存基本释放完毕
在 windows下,其他不同版本的Python结果都相似,那么windows的内存机制是否有别与linux,区别在哪?