• 浅析Python垃圾回收机制!


    Python垃圾回收机制

    1. 内存泄露

    • 程序本身没有设计好,导致程序未能释放已不再使用的内存
    • 代码在分配了某段内存后,因为设计错误,失去了对这段内存的控制,从而造成了内存的浪费

    监控python程序内存占用情况,psutil库

    import os 
    import psutil
    
    # 显示当前程序占用内存大小
    def show_memory_info(hint):
        pid = os.getpid() # 获取当前进程号
        p = psutil.Process(pid)
        info = p.memory_info()
        memory = info.rss / 1024. / 1024
        print(f"{hint} 内存用了:{memory}MB")
    

    查看对象占用内存大小

    import sys
    a = [i for i in range(10000)]
    memory = sys.getsizeof(a) / 1024
    print(f"内存用了:{memory}KB")
    # 内存用了:85.578125KB
    

    2. Python什么时候启动垃圾回收机制?

    2.1 计数引用

    python中一切皆对象,所看到的一切变量,本质上都是对象的一个指针,当这个对象的引用次数为0的时候,说明这个对象永不可达,成为需要被回收的垃圾

    # 查看引用次数
    import sys
    a = []
    print(sys.getrefcount(a)) # 两次引用,一次a,一次getr
    def func(a):
        # 四次引用,函数调用会产生两次额外的引用,一次来自函数栈,另一个是函数参数
        print(sys.getrefcount(a))
    func(a)
    
    2
    4
    
    def func():
        show_memory_info('初始')
        a = [i for i in range(1000000)] # 列表生成式
        show_memory_info('创建之后')
        
    func()
    show_memory_info('结束之后') # 内存即可被释放
    
    初始 内存用了:52.4609375MB
    创建之后 内存用了:91.921875MB
    结束之后 内存用了:53.80859375MB
    
    2.2 循环引用
    • python中使用标记清除算法和分代收集,来启动针对循环引用的自动垃圾回收
    • 标记清除算法,图论中的不可达概念
    • 分代收集算法中每一代都有一个默认阈值,超过指定阈值之后就会启动垃圾回收,如果垃圾回收启动太频繁,会造成程序性能低下,分代收集为了提高性能,因此不立刻回收。
    def func():
        show_memory_info('初始')
        a = [i for i in range(1000000)] # 列表生成式
        b = [i for i in range(1000000)] # 列表生成式
        show_memory_info('创建之后')
        a.append(b)
        b.append(a)
    
    func()
    show_memory_info('结束之后') # 可以看到循环引用之后,内存依旧被占用
    
    初始 内存用了:77.125MB
    创建之后 内存用了:163.8828125MB
    结束之后 内存用了:163.8828125MB
    

    显示调用gc.collect()来启动垃圾回收

    import gc
    
    def func():
        show_memory_info('初始')
        a = [i for i in range(1000000)] # 列表生成式
        b = [i for i in range(1000000)] # 列表生成式
        show_memory_info('创建之后')
        a.append(b)
        b.append(a)
    
    func()
    # 显示调用gc.collect()来启动垃圾回收
    gc.collect()
    show_memory_info('结束之后') 
    
    初始 内存用了:77.609375MB
    创建之后 内存用了:145.92578125MB
    结束之后 内存用了:77.609375MB
    
    问题:引用计数是0是启动垃圾回收的充要条件吗?

    引用计数是其中最简单的实现,不是充要条件,只能算作充分非必要条件,循环引用需要通过不可达判定,来确定是否可以回收。python中自动回收算法包括标记清除算法和分代收集。

  • 相关阅读:
    网页复制内容追加到剪切板
    windows安装 rabbitmq 快速避坑
    springboot rabbitmq快速入门上手(实用)
    python3 websocket客户端
    mybatis查询结果一对多
    mysql 插入数据,存在即更新
    centos7 安装mysql8.0
    收藏一个【fastjson反序列化漏洞原理及利用】
    .NET 5 with Dapr 初体验
    HttpClient缺陷引起的 无法连接到远程服务器 通常每个套接字地址只允许使用一次
  • 原文地址:https://www.cnblogs.com/donghe123/p/13275183.html
Copyright © 2020-2023  润新知