python 优化内存

14 篇文章 0 订阅
2 篇文章 0 订阅

gc

pip install gc

下面是python官方库对其的描述

此模块提供可选垃圾收集器的接口。它提供了禁用收集器,调整收集频率和设置调试选项的功能。它还提供对收集器找到但无法释放的无法访问的对象的访问。由于收集器补充了Python中已经使用的引用计数,因此如果您确定程序不创建引用循环,则可以禁用收集器。可以通过调用禁用自动收集gc.disable()。调试泄漏的程序调用 gc.set_debug(gc.DEBUG_LEAK)。请注意,这包括将 gc.DEBUG_SAVEALL导致垃圾收集的对象保存在gc.garbage中以供检查。

该gc模块提供以下功能:

gc.enable()

启用自动垃圾回收。

gc.disable()

禁用自动垃圾回收。

gc.isenabled()

如果启用了自动收集,则返回true。

gc.collect(代= 2 )

没有参数,运行完整集合。可选参数生成 可以是指定要收集哪一代(从0到2)的整数。ValueError如果世代号无效,则引发A. 返回找到的无法访问的对象数。

每当运行最高代(2)的完整集合或集合时,将清除为多个内置类型维护的空闲列表。特别是,由于特定的实现,并非某些空闲列表中的所有项目都可以被释放float。

gc.set_debug(旗帜)

设置垃圾收集调试标志。将写入调试信息sys.stderr。请参阅下面的调试标志列表,可以使用位操作来控制调试。

gc.get_debug()

返回当前设置的调试标志。

gc.get_objects()

返回收集器跟踪的所有对象的列表,不包括返回的列表。

gc.get_stats(
返回自解释器启动以来包含收集统计信息的三个每代字典的列表。密钥的数量将来可能会更改,但目前每个字典将包含以下项目:

collections 是收集这一代人的次数;

collected 是这一代人收集的对象总数;

uncollectable是garbage 在这一代内部被发现无法收集(因此被移动到列表中)的对象总数。

版本3.4中的新功能。

gc.set_threshold(threshold0 [,threshold1 [,threshold2 ] ] )

设置垃圾收集阈值(收集频率)。将threshold0设置 为零会禁用收集。

GC将对象分为三代,具体取决于它们存活的扫描次数。新对象放置在最年轻的一代(代0)中。如果一个对象在一个集合中存活,它将被移动到下一个老一代。由于世代2是最古老的一代,因此该世代的对象在收集后仍然存在。为了决定何时运行,收集器会跟踪自上次收集以来的对象分配和解除分配的数量。当分配数减去解除分配数超过阈值0时,开始收集。最初只0检查生成。如果生成0已被检查超过阈值1次自生成1已经检查过,然后检查生成1。类似地,threshold2 在收集生成1之前控制生成集合的数量2。

gc.get_count()

将当前集合计数作为元组返回。(count0, count1, count2)

gc.get_threshold()

将当前集合阈值作为元组返回。(threshold0, threshold1, threshold2)

gc.get_referrers(* objs )

返回直接引用任何obj的对象列表。该函数只能找到那些支持垃圾收集的容器; 将找不到引用其他对象但不支持垃圾回收的扩展类型。

请注意,已经被解除引用但是以循环方式存在但尚未被垃圾收集器收集的对象可以列在生成的引用者中。要仅获取当前活动对象,请collect() 在致电前致电get_referrers()。

使用返回的对象时必须小心,get_referrers()因为它们中的一些仍然可能正在构建中,因此处于暂时无效的状态。避免get_referrers()用于除调试之外的任何其他目的。

gc.get_referents(* objs )

返回由任何参数直接引用的对象列表。返回的引用对象是参数’C级 tp_traverse方法(如果有)访问的对象,并且可能不是所有对象实际上都可以直接访问。 tp_traverse方法仅由支持垃圾收集的对象支持,并且只需要访问可能涉及循环的对象。因此,例如,如果可以从参数直接访问整数,则该整数对象可能会也可能不会出现在结果列表中。

gc.is_tracked(obj )

True如果垃圾收集器当前跟踪对象,则返回, False否则返回。作为一般规则,不跟踪原子类型的实例和非原子类型的实例(容器,用户定义的对象…)。但是,可以存在一些特定于类型的优化,以便抑制简单实例的垃圾收集器占用空间(例如,仅包含原子键和值的dicts):

gc.is_tracked(0)
False

gc.is_tracked(“a”)
False

gc.is_tracked([])
True

gc.is_tracked({})
False

gc.is_tracked({“a”: 1})
False

gc.is_tracked({“a”: []})
True
3.1版中的新功能。

为只读访问提供了以下变量(您可以改变值,但不应重新绑定它们):

gc.garbage

收集器发现无法访问但无法释放的对象列表(无法收集的对象)。从Python 3.4开始,此列表在大多数情况下应为空,除非使用具有非NULL tp_del插槽的C扩展类型的实例。

如果DEBUG_SAVEALL已设置,则所有无法访问的对象将添加到此列表而不是释放。

版本3.2中更改:如果此列表在解释器关闭时为非空, ResourceWarning则会发出a,默认情况下为静默。如果 DEBUG_UNCOLLECTABLE已设置,则另外打印所有无法收集的对象。

在版本3.4中更改:以下PEP 442,具有__del__()方法的对象不再结束gc.garbage。

gc.callbacks

收集之前和之后垃圾收集器将调用的回调列表。将使用两个参数(phase和info)调用回调 。

阶段可以是两个值之一:

“开始”:垃圾收集即将开始。

“停止”:垃圾收集已经完成。

info是一个dict,为回调提供更多信息。目前定义了以下键:

“一代”:收集最老一代。

“收集”:当阶段 “停止”时,成功收集的对象数量。

“无法收集”:当阶段 “停止”时,无法收集并放入的对象数量garbage。

应用程序可以将自己的回调添加到此列表中。主要用例是:

收集有关垃圾收集的统计信息,例如收集各代的频率以及收集所需的时间。

允许应用程序在出现时识别并清除自己的无法收集的类型garbage。

版本3.3中的新功能。

提供以下常量用于set_debug():

gc.DEBUG_STATS

收集期间打印统计信息 调整收集频率时,此信息非常有用。

gc.DEBUG_COLLECTABLE

打印有关可收集对象的信息。

gc.DEBUG_UNCOLLECTABLE

打印找到的无法收集的对象的信息(收集器无法访问但无法释放的对象)。这些对象将添加到garbage列表中。

在版本3.2中更改:如果它不为空,garbage也在解释器关闭时打印列表 的内容。

gc.DEBUG_SAVEALL

设置后,找到的所有无法访问的对象都将附加到垃圾而不是被释放。这对于调试泄漏程序非常有用。

gc.DEBUG_LEAK

收集器打印有关泄漏程序的信息(等于)所需的调试标志。DEBUG_COLLECTABLE | DEBUG_UNCOLLECTABLE | DEBUG_SAVEALL

tracemalloc

版本3.4中的新功能。

源代码: Lib / tracemalloc .py

该tracemalloc模块是一个调试工具跟踪被Python分配的内存块。它提供以下信息:

回溯对象的分配位置

每个文件名和每行号分配的内存块的统计信息:已分配内存块的总大小,数量和平均大小

计算两个快照之间的差异以检测内存泄漏

要跟踪Python分配的大多数内存块,应该通过设置模块尽早启动该模块 PYTHONTRACEMALLOC环境变量1,或使用命令行选项。可以在运行时调用该函数以开始跟踪Python内存分配。-X tracemalloctracemalloc.start()

默认情况下,分配的内存块的跟踪仅存储最近的帧(1帧)。要在启动时存储25帧:设置 PYTHONTRACEMALLOC环境变量25,或使用 命令行选项。-X tracemalloc=25
显示分配最多内存的10个文件:

import tracemalloc

tracemalloc.start()

snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')

print("[ Top 10 ]")
for stat in top_stats[:10]:
    print(stat)

Python测试套件的输出示例:

[ Top 10 ]
<frozen importlib._bootstrap>:716: size=4855 KiB, count=39328, average=126 B
<frozen importlib._bootstrap>:284: size=521 KiB, count=3199, average=167 B
/usr/lib/python3.4/collections/__init__.py:368: size=244 KiB, count=2315, average=108 B
/usr/lib/python3.4/unittest/case.py:381: size=185 KiB, count=779, average=243 B
/usr/lib/python3.4/unittest/case.py:402: size=154 KiB, count=378, average=416 B
/usr/lib/python3.4/abc.py:133: size=88.7 KiB, count=347, average=262 B
<frozen importlib._bootstrap>:1446: size=70.4 KiB, count=911, average=79 B
<frozen importlib._bootstrap>:1454: size=52.0 KiB, count=25, average=2131 B
<string>:5: size=49.7 KiB, count=148, average=344 B
/usr/lib/python3.4/sysconfig.py:411: size=48.0 KiB, count=1, average=48.0 KiB
我们可以看到Python 从模块加载数据(字节码和常量),并且模块分配给构建 类型。4855 KiBcollections244 KiBnamedtuple

有关Snapshot.statistics()更多选项,请参阅

27.7.1.2。计算差异
拍摄两张快照并显示差异:

import tracemalloc
tracemalloc.start()
# ... start your application ...

snapshot1 = tracemalloc.take_snapshot()
# ... call the function leaking memory ...
snapshot2 = tracemalloc.take_snapshot()

top_stats = snapshot2.compare_to(snapshot1, 'lineno')

print("[ Top 10 differences ]")
for stat in top_stats[:10]:
    print(stat)

运行Python测试套件的一些测试之前/之后的输出示例:

[ Top 10 differences ]
<frozen importlib._bootstrap>:716: size=8173 KiB (+4428 KiB), count=71332 (+39369), average=117 B
/usr/lib/python3.4/linecache.py:127: size=940 KiB (+940 KiB), count=8106 (+8106), average=119 B
/usr/lib/python3.4/unittest/case.py:571: size=298 KiB (+298 KiB), count=589 (+589), average=519 B
<frozen importlib._bootstrap>:284: size=1005 KiB (+166 KiB), count=7423 (+1526), average=139 B
/usr/lib/python3.4/mimetypes.py:217: size=112 KiB (+112 KiB), count=1334 (+1334), average=86 B
/usr/lib/python3.4/http/server.py:848: size=96.0 KiB (+96.0 KiB), count=1 (+1), average=96.0 KiB
/usr/lib/python3.4/inspect.py:1465: size=83.5 KiB (+83.5 KiB), count=109 (+109), average=784 B
/usr/lib/python3.4/unittest/mock.py:491: size=77.7 KiB (+77.7 KiB), count=143 (+143), average=557 B
/usr/lib/python3.4/urllib/parse.py:476: size=71.8 KiB (+71.8 KiB), count=969 (+969), average=76 B
/usr/lib/python3.4/contextlib.py:38: size=67.2 KiB (+67.2 KiB), count=126 (+126), average=546 B
我们可以看到Python已经加载了模块数据(字节码和常量),并且这比测试之前加载的时间多得多。类似地,该 模块已缓存Python源代码以格式化回溯,所有这些都是自上一个快照以来的。8173 KiB4428 KiBlinecache940 KiB

27.7.2.1。功能

tracemalloc.clear_traces()

清除Python分配的内存块的痕迹。

tracemalloc.get_object_traceback(obj )

获取分配Python对象obj的回溯。返回一个Traceback实例,或者None如果 模块没有跟踪内存分配或者没有跟踪对象的分配。tracemalloc

tracemalloc.get_traceback_limit()

获取存储在跟踪的回溯中的最大帧数。
该模块必须追踪内存分配,以获得极限,否则将引发异常。tracemalloc
限制由start()功能设置。

tracemalloc.get_traced_memory()

获取模块跟踪的内存块的当前大小和峰值大小 作为元组:。tracemalloc(current: int, peak: int)

tracemalloc.get_tracemalloc_memory()

获取用于存储内存块跟踪的模块的内存使用量(以字节为单位)。回来一个。tracemallocint

tracemalloc.is_tracing()

True如果模块正在跟踪Python内存分配,否则。tracemallocFalse

tracemalloc.start(nframe:int = 1 )

开始跟踪Python内存分配:在Python内存分配器上安装挂钩。收集的跟踪回溯将限制为nframe 帧。默认情况下,内存块的跟踪仅存储最新的帧:限制为1。nframe必须大于或等于1。
存储多个1帧仅对计算按统计信息分组的统计信息’traceback’或计算累积统计信息非常有用:请参阅
存储更多帧会增加模块的内存和CPU开销 。使用此功能可以测量模块使用的内存量。tracemallocget_tracemalloc_memory()tracemalloc
该 PYTHONTRACEMALLOCenvironment variable()和 命令行选项可用于在启动时开始跟踪。PYTHONTRACEMALLOC=NFRAME-X tracemalloc=NFRAME

tracemalloc.stop()

停止跟踪Python内存分配:卸载Python内存分配器上的挂钩。还清除以前收集的所有Python分配的内存块跟踪。
调take_snapshot()函数在清除跟踪之前拍摄跟踪的快照。

tracemalloc.take_snapshot()

拍摄Python分配的内存块的快照。返回一个新 Snapshot实例。

快照不包括在模块开始跟踪内存分配之前分配的内存块 。tracemalloc

跟踪的回溯仅限于get_traceback_limit()帧。使用函数的nframe参数start()存储更多帧。

该模块必须跟踪内存分配到拍摄快照,看功能。tracemallocstart()

另请参见该get_object_traceback()功能。

更多详细的信息可以查看官方对库的解释

https://docs.python.org/3.6/library/

简单demo测试tracemalloc


import gc
import tracemalloc
import time

tracemalloc.start() # 开始跟踪内存分配

d = [x for x in range(100000)]
t = []
for i in d :
    t.append(i)
time.sleep(10)
tracemalloc.clear_traces()
print(t[:10])

snapshot = tracemalloc.take_snapshot() # 快照,当前内存分配
top_stats = snapshot.statistics('lineno') # 快照对象的统计
unreachable_count = gc.collect()
print(unreachable_count)
unreachable_count = gc.get_threshold()
print(unreachable_count)
for stat in top_stats:
    print(stat)
print(t[100:110])
time.sleep(20)

睡眠前占的内存
在这里插入图片描述
优化后占的内存
在这里插入图片描述
运行结果
在这里插入图片描述

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值