zoukankan      html  css  js  c++  java
  • 排查python内存泄露中几个工具的使用

    本文主要介绍3个工具:pdb,objgraph,以及pympler。

    1.pdb

    pdb是专门用于python代码调试,模仿gdb。
    使用pdb可以查看堆栈,打印变量等。

    这里介绍的是命令行下的pdb。
    命令行下使用pdb,代码侵入小,调试方便。

    本例中,python安装在当前目录下.venv

    使用pdb加载python程序

    .venv/bin/python -m pdb  orange.py
    > /Users/lanyang/workspace/orange/orange.py(3)<module>()
    -> import inspect
    (Pdb)
    

    启动程序

    (Pdb)c
    

    这样,python代码就开始执行了。

    相关的命令有

    • bt 打印堆栈
    • q 退出
    • pp 打印变量
    • c(ont(inue)) 继续执行

    更多命令可参考:

    (Pdb) help
    
    Documented commands (type help <topic>):
    ========================================
    EOF    c          d        h         list      q        rv       undisplay
    a      cl         debug    help      ll        quit     s        unt
    alias  clear      disable  ignore    longlist  r        source   until
    args   commands   display  interact  n         restart  step     up
    b      condition  down     j         next      return   tbreak   w
    break  cont       enable   jump      p         retval   u        whatis
    bt     continue   exit     l         pp        run      unalias  where
    
    Miscellaneous help topics:
    ==========================
    exec  pdb
    

    2.objgraph

    安装objgraph

    pip install objgraph
    

    查看最常用的类型

    (Pdb) import objgraph
    (Pdb) objgraph.show_most_common_types(limit=20)
    function                   22750
    dict                       15520
    tuple                      12536
    weakref                    6679
    list                       5516
    type                       3449
    getset_descriptor          3408
    cell                       2566
    set                        2496
    ModuleSpec                 1588
    module                     1582
    SourceFileLoader           1502
    wrapper_descriptor         1332
    builtin_function_or_method 1241
    method_descriptor          1219
    property                   1171
    member_descriptor          822
    classmethod                697
    WeakSet                    571
    MovedAttribute             501
    

    感觉这个函数没什么用。

    查看增长最快的类型

    (Pdb) objgraph.show_growth(limit=10)
    function             22749    +22749
    dict                 15515    +15515
    tuple                12332    +12332
    weakref               6680     +6680
    list                  5517     +5517
    type                  3449     +3449
    getset_descriptor     3408     +3408
    cell                  2565     +2565
    set                   2496     +2496
    ModuleSpec            1588     +1588
    

    show_growth()打印两次调用之间增加的类型。如果这其中有自己定义的类型,很可能就是问题所在。如果都是python内置类型,可能要花费更多功夫了。

    一般排查问题时,在程序开始执行时,调用show_growth(),程序跑一段时间后,再次调用show_growth(),查看哪些对象增长最快。

    如果使用pdb在命令行下调试,ctrl+c停止程序的时候,注意观察上下文,保证跟上次import objgraph时一样,否则,会出现:

    (Pdb) objgraph.show_growth(limit=10)
    *** NameError: name 'objgraph' is not defined
    (Pdb)
    

    如果出现这个问题,可以继续让程序执行,再ctrl+c停止程序。

    查看某个类型

    (Pdb) objgraph.by_type('list')
    

    这个可能会打印一堆。

    3.pympler

    使用objgraph时,虽然可以看到增长最快的对象,但是无法得知占用内存最多的是哪个。

    下面我们就使用pympler,查看内存占用。

    (Pdb) from pympler import tracker
    (Pdb) tr = tracker.SummaryTracker()
    (Pdb) tr.print_diff()
                      types |   # objects |   total size
    ======================= | =========== | ============
               <class 'list |       12769 |      1.18 MB
                <class 'str |       12769 |    950.47 KB
                <class 'int |        2513 |     68.71 KB
               <class 'code |           1 |    144     B
      function (store_info) |           1 |    136     B
               <class 'cell |           2 |     96     B
              <class 'tuple |           1 |     64     B
             <class 'method |          -1 |    -64     B
               <class 'dict |           0 |   -128     B
    (Pdb) tr.print_diff()
             types |   # objects |   total size
    ============== | =========== | ============
      <class 'list |           1 |     88     B
       <class 'str |           1 |     70     B
    (Pdb) tr.print_diff()
      types |   # objects |   total size
    ======= | =========== | ============
    (Pdb)
    

    tracker对象初始化的时候会创建一个summary,每次调用tracker.print_diff()的时候又会创建一个summary,当前的summary与上次的summary做比较,并打印两者之间的不同。

    4.参考

    pdb

    objgraph

    pympler

    pympler muppy

    Python内存泄露调试指导思想

    使用gc、objgraph干掉python内存泄露与循环引用!

    python 进程内存增长问题, 解决方法和工具

  • 相关阅读:
    SQL
    第九章
    第三章 表单
    第二章 表格,列表,媒体元素
    HTML5基础
    Java第一本书总复习
    字符串
    人机猜拳
    类的无参方法
    类和对象
  • 原文地址:https://www.cnblogs.com/lanyangsh/p/11523753.html
Copyright © 2011-2022 走看看