【笔记】:谁偷了我的内存?

内存占用

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,区别在哪?

 

原文地址:https://www.cnblogs.com/lianzhilei/p/9035274.html