当前位置: 首页 > news >正文

Python内存使用分析工具深度解析与实践指南(下篇)

文章目录

    • 引言
    • 6. guppy3 / Heapy
      • 功能
      • 安装
      • 程序示例
      • 适用场景
      • 注意事项
    • 7. objgraph
      • 功能
      • 安装
      • 程序示例
      • 适用场景
      • 注意事项
    • 8. memory_profiler
      • 功能
      • 安装
      • 程序示例
      • 适用场景
      • 注意事项
    • 9. profile(标准库)
      • 功能
      • 程序示例
      • 适用场景
      • 注意事项
    • 总结对比表


引言

在Python编程领域,内存使用情况的分析是保障程序高效运行的关键一环。上篇文章中,我们介绍了sys.getsizeof()pandas.Series.memory_usage()等5种内存分析工具。本篇将继续探讨另外4种实用工具,它们分别是guppy3 / Heapyobjgraphmemory_profiler以及profile的基本应用,帮助你全面掌握Python内存分析的方法与技巧。

6. guppy3 / Heapy

功能

guppy3库中的Heapy模块专注于提供对象堆的详细统计信息,涵盖内存中各类对象的数量、大小以及它们之间的引用关系。借助这些丰富的数据,开发者可以清晰洞察内存使用的全貌,精准定位内存占用大户,为优化内存性能提供有力的数据支撑。

安装

uv add guppy3

程序示例

from guppy3 import hpy
import pandas as pd# 示例1:获取整体内存使用统计信息
h = hpy()
print("整体内存使用统计信息:")
print(h.heap())# 示例2:分析包含大量数据的Series的内存使用
series = pd.Series([i for i in range(1000000)])
print("\n包含大量数据的Series的内存使用统计信息:")
print(h.heap())

结果示例:

整体内存使用统计信息:
Partition of a set of 206701 objects. Total size = 31499990 bytes.Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)0  60983  30  9039272  29   9039272  29 str1  13414   6  5615712  18  14654984  47 types.CodeType2  48136  23  3763128  12  18418112  58 tuple3  28650  14  2565668   8  20983780  67 bytes4  13448   7  2151680   7  23135460  73 function5   1660   1  1917024   6  25052484  80 type6   3834   2  1002336   3  26054820  83 dict (no owner)7    599   0   728296   2  26783116  85 dict of module8   1520   1   652120   2  27435236  87 dict of type9    350   0   302160   1  27737396  88 set
<583 more rows. Type e.g. '_.more' to view.>包含大量数据的Series的内存使用统计信息:
Partition of a set of 206302 objects. Total size = 47462422 bytes.Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)0  60983  30  9039272  19   9039272  19 str1     39   0  8004020  17  17043292  36 numpy.ndarray2      1   0  8000164  17  25043456  53 pandas.core.series.Series3  13412   7  5615216  12  30658672  65 types.CodeType4  47989  23  3752568   8  34411240  73 tuple5  28644  14  2565392   5  36976632  78 bytes6  13300   6  2128000   4  39104632  82 function7   1660   1  1917024   4  41021656  86 type8   3837   2  1002648   2  42024304  89 dict (no owner)9    599   0   728296   2  42752600  90 dict of module
<592 more rows. Type e.g. '_.more' to view.>

运行上述代码,h.heap()方法输出的信息会展示内存中不同对象类型的分布、数量以及内存占用大小。通过对比示例1和示例2的结果,能够直观地看到Series对象对整体内存使用的影响。

适用场景

guppy3 / Heapy适用于深度内存分析场景,尤其是在优化大型应用程序时,开发者需要全面了解内存中各类对象的分布情况,找出内存占用较高的对象类型及其引用关系,进而针对性地进行内存优化。例如,在处理复杂的数据分析项目或大型Web应用时,该工具可助力开发者深入剖析内存使用状况。

注意事项

在处理大规模数据或复杂内存结构时,guppy3可能会消耗较多系统资源,导致分析过程耗时较长。此外,其输出信息较为复杂,需要开发者具备一定的内存分析经验,才能准确理解和利用这些数据。

7. objgraph

功能

objgraph库的核心功能是可视化对象之间的引用关系,这对于排查内存泄漏问题极为有效。它能够以图形化的方式呈现对象引用网络,让开发者直观地发现循环引用等潜在问题。同时,objgraph还提供了查看内存中数量最多的对象类型、对象实例数量等实用功能,帮助开发者初步了解内存使用概况。

安装

使用objgraph前,需执行以下安装命令:

pip install objgraph

生成图片需要下载并安装graphviz
下载地址:https://graphviz.org/download/#windows

程序示例

import objgraph
import pandas as pd# 示例1:查看内存中数量最多的对象类型
objgraph.show_most_common_types()# 示例2:模拟循环引用并可视化引用关系
class Node:def __init__(self):self.next = Nonea = Node()
b = Node()
a.next = b
b.next = aobjgraph.show_backrefs([a], filename='循环引用.png')

执行结果:

function                   12831
tuple                      6496
dict                       5045
wrapper_descriptor         2924
ReferenceType              2327
cell                       2212
getset_descriptor          2156
method_descriptor          1988
list                       1824
builtin_function_or_method 1614
Graph written to C:\Users\xxx\AppData\Local\Temp\objgraph-jlwhcz6b.dot (7 nodes)
Image generated as 循环引用.png

循环引用.png
请添加图片描述

示例1通过show_most_common_types()方法,快速展示内存中数量占比较大的对象类型。示例2模拟了循环引用场景,并使用show_backrefs()方法将对象引用关系生成图片,方便开发者直观地分析循环引用结构。

适用场景

当开发者怀疑程序存在内存泄漏,但难以定位具体原因时,objgraph是绝佳的选择。通过可视化对象引用关系,能够快速锁定存在问题的对象及其引用路径,从而有效解决内存泄漏问题。此外,在理解复杂数据结构或对象关系时,该工具也能提供直观的辅助。

注意事项

对于大规模复杂的对象网络,objgraph生成的可视化图形可能会过于繁杂,影响分析效率。使用可视化功能时,需确保系统安装了相应的图形生成依赖(如graphviz),否则可能无法正常生成图形。

8. memory_profiler

功能

memory_profiler是一款强大的Python内存分析库,它能让开发者直观地了解每一行代码的内存消耗情况。主要通过两种方式实现:一是使用装饰器@profile标记函数,运行程序后可查看函数内每行代码的内存占用;二是在Jupyter Notebook中利用魔法命令%mprun%memit进行内存分析,%mprun用于分析整个函数的内存使用,%memit则可快速查看单行代码的内存消耗。

安装

首先安装memory_profiler

uv add memory-profiler

程序示例

创建memory_test.py脚本:
使用装饰器@profile

from memory_profiler import profile@profile
def create_large_list():data = []for i in range(100000):data.append(i)return dataif __name__ == "__main__":create_large_list()

执行结果:

Line #    Mem usage    Increment  Occurrences   Line Contents
=============================================================3     24.5 MiB     24.5 MiB           1   @profile4                                         def create_large_list():5     24.5 MiB      0.0 MiB           1       data = []6     28.8 MiB      0.0 MiB      100001       for i in range(100000):7     28.8 MiB      4.2 MiB      100000           data.append(i)8     28.8 MiB      0.0 MiB           1       return data

显示执行时每行代码的内存使用情况。

也可在Jupyter Notebook中使用魔法命令

# 安装并加载扩展
%pip install memory-profiler
%load_ext memory_profiler# 使用 %memit 查看单行代码内存使用
%memit [i for i in range(100000)]# 定义函数并使用 %mprun 分析函数内存使用
def create_dict():my_dict = {}for i in range(10000):my_dict[i] = str(i)return my_dict%mprun -f create_dict create_dict()

%memit输出单行代码的内存消耗估算值,%mprun详细打印函数内每行代码的内存增量和累计使用情况。

适用场景

memory_profiler特别适用于检测循环、数据加载、大量对象创建等操作的内存消耗。在代码优化过程中,若开发者想要精准定位高内存消耗的代码行,该工具能提供详细且直观的分析结果,为优化数据处理逻辑或数据结构提供依据。

注意事项

使用装饰器方式时,在生产环境中应移除@profile装饰器,以免影响程序性能。memory_profiler的分析结果可能受系统其他进程内存使用情况的干扰,导致结果存在一定波动。对于底层内存操作或与C扩展模块相关的内存使用,它的统计准确性可能会受到影响。

9. profile(标准库)

功能

profile是Python标准库中的性能分析工具,主要用于分析程序的CPU执行时间,同时也能间接辅助内存使用分析。通过profile,开发者可以获取函数调用次数、执行时间等信息,基于这些数据,结合代码逻辑和内存分配原理,能够推测出哪些函数可能存在内存分配频繁或占用大量内存的情况。

程序示例

import profiledef fibonacci(n):if n <= 1:return nreturn fibonacci(n - 1) + fibonacci(n - 2)def calculate_fibonacci_sequence():result = []for i in range(30):result.append(fibonacci(i))return resultif __name__ == "__main__":profile.run('calculate_fibonacci_sequence()')

执行结果:

         4356621 function calls (65 primitive calls) in 25.422 secondsOrdered by: standard namencalls  tottime  percall  cumtime  percall filename:lineno(function)30    0.000    0.000    0.000    0.000 :0(append)1    0.000    0.000   25.328   25.328 :0(exec)1    0.094    0.094    0.094    0.094 :0(setprofile)1    0.000    0.000   25.328   25.328 <string>:1(<module>)1    0.000    0.000   25.422   25.422 profile:0(calculate_fibonacci_sequence())0    0.000             0.000          profile:0(profiler)
4356586/30   25.328    0.000   25.328    0.844 test.py:3(fibonacci)1    0.000    0.000   25.328   25.328 test.py:8(calculate_fibonacci_sequence)

执行上述代码,profile.run输出函数调用的统计信息,包括函数名、调用次数、总时间、每次调用的累计时间和原始时间等。通过分析fibonacci函数的调用情况,可推测该递归函数可能因大量函数调用和中间数据存储,导致内存占用较高。

适用场景

profile适用于对程序进行全面性能分析的场景。当开发者需要综合考量CPU和内存使用情况,寻找程序性能瓶颈时,profile提供的函数级调用统计信息,可辅助定位存在问题的函数区域,再结合其他内存分析工具进一步深入分析。

注意事项

profile无法直接获取内存使用的具体数据,其分析结果主要基于CPU时间,对于I/O密集型操作或与内存管理机制紧密相关的问题,可能无法准确反映实际情况。实际使用中,通常需要与其他专门的内存分析工具配合使用,以获得更全面的性能分析结果。

总结对比表

工具/方法是否递归统计是否精确是否可视化是否需安装推荐用途
sys.getsizeof()快速查看基本数据类型或简单容器浅层大小
pandas.Series.memory_usage()估算Series对象及其索引内存(不深入)
pandas.Series.memory_usage(deep=True)精确统计Series对象及其内部对象的内存
pympler.asizeof()统计任意对象及其引用对象的实际内存
tracemalloc调试内存分配与泄漏,追踪内存分配源头
guppy3/Heapy深度分析堆内存,了解对象类型分布与引用关系
objgraph✅(图形化)内存泄漏定位与对象引用关系可视化分析
memory_profiler函数级逐行内存分析,定位高内存消耗代码行
profile综合性能分析,辅助定位可能的内存问题区域

通过对这9种Python内存分析工具的详细介绍,相信你对如何分析和优化程序内存使用有了更深入的理解。不同的工具在功能、适用场景和使用方式上各有优劣,在实际项目中,根据具体需求灵活选择和组合这些工具,才能高效地解决内存相关问题,提升Python程序的性能与稳定性。如果你在使用过程中遇到任何问题,或者有新的见解,欢迎随时交流分享。

http://www.lqws.cn/news/463879.html

相关文章:

  • 江科大STM32入门:DMA传输数据
  • java 找出两个json文件的不同之处
  • 神经网络中的均方误差(Mean Squared Error)详解
  • 自定义OceanBase集群安装并使用OCP接管集群
  • 【DCS开源项目】—— Lua 如何调用 DLL、DLL 与 DCS World 的交互
  • LeetCode第279题_完全平方数
  • Vue3 的生命周期:从 Composition API 视角看
  • DeepEP开源MoE模型分布式通信库
  • Linux运维新人自用笔记(Ubuntu磁盘命名规则、新磁盘分区、主流文件系统类型、mkfs命令格式化文件系统、临时和永久挂载、挂载报错、dd指令)
  • 2.7 Python方法调用机制解析:从描述符到字节码执行
  • 5.2 Qt Creator 使用FFmpeg库
  • win环境使用openssl创建p12证书
  • 微前端MFE:(React 与 Angular)框架之间的通信方式
  • word-spacing 属性
  • Kubernetes控制平面组件:Kubelet详解(八):容器存储接口 CSI
  • C++链表的虚拟头节点
  • 课程目录:腾讯混元3D × Unity3D全流程开发
  • Python pytesseract【OCR引擎库】 简介
  • 【JVM|内存结构】第一天
  • 【论文笔记】【强化微调】TinyLLaVA-Video-R1:小参数模型也能视频推理
  • Spring-MyBatis基本操作
  • linux weston flutter remote desktop
  • 2025年- H83-Lc191--139.单词拆分(动态规划)--Java版
  • JF - 600MT称重变送器与Modbus TCP转Profibus DP网关通讯案例
  • MCPServer编程与CLINE配置调用MCP
  • 项目练习:Jaspersoft Studio制作PDF报表时,detail和column footer之间存在很大的空白区
  • SkyWalking探针技术监控Spring Boot微服务——部署与应用详解
  • Laravel 项目中图片上传后无法访问的问题
  • 进程间通信——管道
  • 【Qt开发】网络运用