Python旨在去除C和C++等语言中涉及的大量复杂内存管理。当对象超出范围时,它会自动被垃圾回收。然而,对于使用Python开发的大型、长时间运行的系统,内存管理是不容小觑的事情。在这篇博客中,我将分享有关减少Python内存消耗的方法,并分析内存消耗/膨胀的根本原因。这些都是在实际操作中总结出来的经验。我们正在构建DatosIO的RecoverX分布式备份和恢复平台。这里主要介绍Python开发(C++、Java、bash也有类似的组件)。Python垃圾收集Python解释器对正在使用的对象进行计数。当对象不再被引用指向时,垃圾收集器可以释放该对象并获得分配的内存。例如,如果您使用常规Python(CPython,而不是JPython),Python的垃圾收集器将调用free()/delete()。Utility1.资源(resource)'resource'模块用于查看项目当前固有内存消耗【固有内存是项目实际使用的RAM】2.对象(objgraph)'objgraph'是一个实用的可以显示内存中当前对象的模块【objgraph文档和实例地址:https://mg.pov.lt/objgraph/】我们来看看objgraph的简单用法:注意我们仍然持有10,423个'dict'实例在内存对象中。3.可视化objgraph依赖关系Objgraph有一个很好的功能,可以显示Foo()对象在内存中存在的因素,即谁持有对它的引用(在这种情况下列出'l')。在RedHat/Centos上,可以使用sudoyuminstallyuminstallgraphviz*安装graphviz查看对象字典,d,请参考:objgraph.show_refs(d,filename='sample-graph.png')从内存使用看,我们很惊讶——为什么对象没有被释放?这是因为有人持有对它的引用。这个小片段展示了objgraph如何提供相关信息:在本例中,我们查看一个Foo类型的随机对象。我们知道这个特定的对象保存在内存中,因为它的引用链接在指定的范围内。有时,上述技巧可以帮助我们理解为什么当我们不再使用一个对象时,Python垃圾收集器不收集垃圾。棘手的部分是有时我们发现带有Foo()的类占用了大量内存。此时我们可以使用heapy()来回答上面的问题。4.Heapyheapy是调试内存消耗/泄漏的实用工具。查看http://guppy-pe.sourceforge.net/。通常,我将objgraph和heapy一起使用:使用heapy可以看到分配对象随时间增长的差异,heapy可以显示对象持有的最大内存等;使用Objgraph寻找backref链(例如:前4个sections),尝试得到它们不能被release的原因。Heapy的一个典型用途是在代码的不同地方调用一个函数,试图提供大量内存使用的线索,并找出可能导致的问题:TipsforreducingmemoryconsumptionMemoryConsumptionTips。当你有很多对象时,可以使用插槽。插槽与Python解释器通信:你的对象不需要动态字典(从上面的例子2.2,我们看到每个Foo()对象里面都包含一个字典)用插槽定义你的对象,让python解释器知道你的类属性/members是固定的。。这样可以有效的节省内存!参考以下代码:在这个例子中,内存消耗减少了60%!驻留:当心驻留字符串!Python记录字符串等不可变值(大小取决于实现),这叫做持久化。这是由python解析器完成的,它可以节省内存并加快比较速度。例如,如果两个字符串具有相同的ID或引用-它们是相同的。但是,如果您的程序创建了许多小字符串,您的内存就会膨胀。生成字符串时使用Format而不是“+”接下来,在构造字符串时使用Format而不是“+”来构建字符串。也就是说,在我们的系统中,当我们将一些字符串构造从“+”更改为使用格式时,可以显着节省内存。我们上面在系统级别讨论的技术可以帮助您发现系统内存消耗的问题。然而,python进程产生的内存消耗随着时间的推移不断增加。这似乎与问题有关:为什么C中的内存分配在Python内部起作用,这本质上是由内存碎片引起的。因为,除非不使用整个内存,否则分配过程无法调用“free”方法。但是需要注意的是,内存的使用并不是按照你创建和使用的对象来安排的。内存的增加也与上面讨论的“Interning”有关。根据我的经验,减少python中的内存消耗比率是有效的。在DatosIO中,我曾经为一个指定的内存消耗进程实现了一个worker模块。对于序列化的工作单元,我们运行一个工作进程。工作进程完成后,它会被删除——这是返回系统全部内存的唯一有效方法:)。良好的内存管理允许增加分配内存的大小,即允许工作进程运行很长时间。综上所述,我总结了一些减少python进程内存消耗的技巧。当我们在代码中查找内存泄漏时,一种方法是通过使用Heapy找出哪个Obj占用了更多的内存,然后使用Objgraph找出释放内存的位置。原因(除非你认为他们应该被释放)。总的来说,我发现在python中查找内存问题是一门学科。随着时间的推移,您会对系统中的内存膨胀和泄漏产生直觉,并更快地解决它们。祝你发现问题愉快!
