• 如何分析python的性能(linux)


    一.多进程:

      查看程序所有进程与线程

      如果python程序启动后形成多个进程如何判断其关系

      显示进程的树状结构。-cp 表示树展开,且显示进程号码

    $pstree -cp

      显示结果

            │               │               │            ├─pycharm.sh(5146)───java(5194)─┬─fsnotifier64(5232)
            │               │               │            │                               ├─python2.7(5314)─┬─python2.7(5327)─┬─{python2.7}(5329)
            │               │               │            │                               │                 │                 ├─{python2.7}(5330)
            │               │               │            │                               │                 │                 ├─{python2.7}(5341)
            │               │               │            │                               │                 │                 └─{python2.7}(5344)
            │               │               │            │                               │                 ├─python2.7(5328)─┬─{python2.7}(5339)
            │               │               │            │                               │                 │                 ├─{python2.7}(5340)
            │               │               │            │                               │                 │                 ├─{python2.7}(5354)
            │               │               │            │                               │                 │                 └─{python2.7}(5355)
            │               │               │            │                               │                 ├─python2.7(5331)─┬─{python2.7}(5342)
            │               │               │            │                               │                 │                 ├─{python2.7}(5343)
            │               │               │            │                               │                 │                 ├─{python2.7}(5359)
            │               │               │            │                               │                 │                 └─{python2.7}(5360)
            │               │               │            │                               │                 ├─python2.7(5332)─┬─{python2.7}(5346)
            │               │               │            │                               │                 │                 ├─{python2.7}(5347)
            │               │               │            │                               │                 │                 ├─{python2.7}(5364)
            │               │               │            │                               │                 │                 └─{python2.7}(5365)
            │               │               │            │                               │                 ├─python2.7(5333)─┬─{python2.7}(5348)
            │               │               │            │                               │                 │                 ├─{python2.7}(5350)
            │               │               │            │                               │                 │                 ├─{python2.7}(5368)
            │               │               │            │                               │                 │                 └─{python2.7}(5369)
            │               │               │            │                               │                 ├─python2.7(5334)─┬─{python2.7}(5356)
            │               │               │            │                               │                 │                 ├─{python2.7}(5358)
            │               │               │            │                               │                 │                 ├─{python2.7}(5376)
            │               │               │            │                               │                 │                 └─{python2.7}(5377)
            │               │               │            │                               │                 ├─python2.7(5335)─┬─{python2.7}(5352)
            │               │               │            │                               │                 │                 ├─{python2.7}(5353)
            │               │               │            │                               │                 │                 ├─{python2.7}(5373)
            │               │               │            │                               │                 │                 └─{python2.7}(5375)
            │               │               │            │                               │                 ├─python2.7(5336)─┬─{python2.7}(5362)
            │               │               │            │                               │                 │                 ├─{python2.7}(5363)
            │               │               │            │                               │                 │                 ├─{python2.7}(5378)
            │               │               │            │                               │                 │                 └─{python2.7}(5379)
            │               │               │            │                               │                 ├─python2.7(5337)─┬─{python2.7}(5372)
            │               │               │            │                               │                 │                 ├─{python2.7}(5374)
            │               │               │            │                               │                 │                 ├─{python2.7}(5382)
            │               │               │            │                               │                 │                 └─{python2.7}(5383)
            │               │               │            │                               │                 ├─python2.7(5338)─┬─{python2.7}(5366)
            │               │               │            │                               │                 │                 ├─{python2.7}(5370)
            │               │               │            │                               │                 │                 ├─{python2.7}(5380)
            │               │               │            │                               │                 │                 └─{python2.7}(5381)
            │               │               │            │                               │                 ├─{python2.7}(5317)
            │               │               │            │                               │                 ├─{python2.7}(5318)
            │               │               │            │                               │                 └─{python2.7}(5319)
            │               │               │            │                               ├─{java}(5195)

      从上面可以看到,python程序起了一个主进程5314,然后这个主进程又起了10个左右的子进程。再结合以下命令可以判断出启动的程序的组成主进程是那个,以及子进程是那个。

    $ps aux|grep 程序名 

      查看某个进程的状态

    $top -H -p N  ###N是进程号
    $cat /proc/N/status ###N是进程号

      例子1:查看主进程5314

    $cat /proc/5314/status

      显示信息如下

    Name:    python2.7               ###进程名字
    State:    S (sleeping)             ###进程状态
    Tgid:    5314                  ###进程线程组id(主线程),也就是进程id;每个进程有一个主线程,有其他线程;主线程id即进程id 
    Ngid:    0                    ###
    Pid:    5314                   ###线程或者进程id(主线程),linux中线程进程是同一个数据结构
    PPid:    5194                  ###父进程id
    TracerPid:    0                 ###跟踪当前进程的进程id,0表示无跟踪
    Uid:    1000    1000    1000    1000    ###用户id
    Gid:    0    0    0    0           ###组id
    FDSize:    512                 ###文件描述符上限,ls /proc/5314/fd;查看文件描述符
    Groups:    0 4 24 27 30 46 108 124 127   ###用户组
    VmPeak:      329196 kB            ###进程运行占用内存的峰值
    VmSize:      329192 kB            ###目前占用内存量
    VmLck:           0 kB             ###进程锁住的内存,不能交换到磁盘
    VmPin:           0 kB             ###
    VmHWM:       45860 kB             ###程序得到分配到物理内存的峰值
    VmRSS:       45860 kB             ###程序得到分配到物理内存
    VmData:      259188 kB            ###表示进程数据段的大小
    VmStk:         136 kB             ###表示进程堆栈段的大小
    VmExe:        2800 kB             ###表示进程代码的大小.
    VmLib:        6088 kB             ###表示进程所使用LIB库的大小.
    VmPTE:         240 kB             ###占用的页表的大小
    VmSwap:           0 kB            ###进程占用Swap交换区的大小
    Threads:    4                  ###进程下面的线程个数
    SigQ:    0/64045                 ###表示当前待处理信号的个数
    SigPnd:    0000000000000000         ###屏蔽位,存储了该线程的待处理信号,等同于线程的PENDING信号.
    ShdPnd:    0000000000000000          ###屏蔽位,存储了该线程组的待处理信号.等同于进程组的PENDING信号.
    SigBlk:    0000000000000004         ###存放被阻塞的信号,等同于BLOCKED信号.
    SigIgn:    0000000001001000         ###存放被忽略的信号,等同于IGNORED信号.
    SigCgt:    0000000180004003         ###存放捕获的信号,等同于CAUGHT信号.
    CapInh:    0000000000000000         ###能够被当前进程执行的程序继承的能力.
    CapPrm:    0000000000000000         ###表示进程能够使用的能力
    CapEff:    0000000000000000         ###当一个进程要进行某个特权操作时,操作系统会检查cap_effective的对应位是否有效,而不再是检查进程的有效UID是否为0.
    CapBnd:    0000003fffffffff         ###是系统的边界能力,我们无法改变它.
    Seccomp:    0                  ###
    Cpus_allowed:    ffffffff           ###该进程可以使用CPU的亲和性掩码,如果我们指定为两块CPU,这里就是3,如果该进程指定为4个CPU(如果有话),这里就是F(1111).
    Cpus_allowed_list:    0-31          ###进程可以使用的cpu的id号码列表
    Mems_allowed:    00000000,00000001     ###内存资源
    Mems_allowed_list:    0            ###内存资源
    voluntary_ctxt_switches:    376135     ###进程主动切换的次数
    nonvoluntary_ctxt_switches:    5992    ###进程被动切换的次数

     二.内存

      查看可执行文件的镜像

    $readelf -s xxx   ###xxx为可执行文件的路径,linux上可执行文件是elf文件格式的。

      例子1:

      查看python执行程序

    $readelf -s /usr/bin/python2.7

      可以看到该执行文件的结构,但是python程序本身是字节码文件,不是elf文件。因此这个对我们作用不大

      1656: 0000000000503ef0    72 FUNC    GLOBAL DEFAULT   13 PySequence_Size
      1657: 0000000000934cd0     8 OBJECT  GLOBAL DEFAULT   25 _PyIO_locale_module
      1658: 00000000005b6150    20 FUNC    GLOBAL DEFAULT   13 _PyLong_Sign
      1659: 000000000043aa0b   100 FUNC    GLOBAL DEFAULT   13 PyCodec_Register
      1660: 00000000004c9ff0   201 FUNC    GLOBAL DEFAULT   13 PyObject_CallFunction
      1661: 0000000000465e20    37 FUNC    GLOBAL DEFAULT   13 _Py_c_prod
      1662: 00000000004554c1    35 FUNC    GLOBAL DEFAULT   13 PyFunction_GetModule
      1663: 000000000044d09b   715 FUNC    GLOBAL DEFAULT   13 PyImport_ReloadModule
      1664: 0000000000465adb     9 FUNC    GLOBAL DEFAULT   13 PyFloat_GetMin
      1665: 000000000090f6e0   392 OBJECT  GLOBAL DEFAULT   24 PyCell_Type
      1666: 0000000000456f41     8 FUNC    GLOBAL DEFAULT   13 PyComplex_FromDoubles
      1667: 0000000000918320     4 OBJECT  GLOBAL DEFAULT   24 _PyOS_opterr
      1668: 000000000091a6c0     8 OBJECT  GLOBAL DEFAULT   24 PyExc_OverflowError
      1669: 000000000051ce20   161 FUNC    GLOBAL DEFAULT   13 PyClass_IsSubclass
      1670: 000000000090e3a0   392 OBJECT  GLOBAL DEFAULT   24 PyProperty_Type
      1671: 0000000000907620   392 OBJECT  GLOBAL DEFAULT   24 PyRange_Type
      1672: 00000000004667c2     6 FUNC    GLOBAL DEFAULT   13 _Py_svnversion
      1673: 0000000000581a10   189 FUNC    GLOBAL DEFAULT   13 PyNumber_Float

      查看进程内存镜像

    $cat /proc/N/maps

    三.执行时间

      系统自带的时间分析

    $ time python xxx.py     

      显示结果为

    real    0m1.028s    ###真实执行时间,等待IO时间,在cpu内核与用户态执行时间
    user    0m0.001s    ###用户态cpu执行时间
    sys     0m0.003s    ###系统态cpu执行时间

      使用python的time模块

    import time
    
    class Timer(object):
        def __init__(self, verbose=False):
            self.verbose = verbose
    
        def __enter__(self):
            self.start = time.time()
            return self
    
        def __exit__(self, *args):
            self.end = time.time()
            self.secs = self.end - self.start
            self.msecs = self.secs * 1000  # millisecs
            if self.verbose:
                print 'elapsed time: %f ms' % self.msecs

      使用cprofile工具,

     

    $python -m cProfile -o result.out xxx.py    ###result.out为保存结果的文件

        使用pstats分析result.out

    $python -m pstats result.out 

        结果如下

    8 function calls in 0.042 seconds
     
       Ordered by: cumulative time
     
       ncalls  tottime  percall  cumtime  percall filename:lineno(function)
            1    0.000    0.000    0.042    0.042 test.py:5(<module>)
            1    0.002    0.002    0.042    0.042 test.py:12(test)
            2    0.035    0.018    0.039    0.020 test.py:5(sum_num)
            3    0.004    0.001    0.004    0.001 {range}
            1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

        结果列分别为:调用次数,总时间,每次调用平均时间,函数与子函数总时间,函数与子函数平均时间,文件名称,行号

        使用图形化分析工具Gprof2Dot,visualpytune,KCacheGrind分析result.out

    $python gprof2dot.py -f pstats result.out | dot -Tpng -o result.png

      工具

      工具line_profiler

        可以分析每行代码的执行时间

      工具memory_profiler

        可以分析每行代码的内存变化

      工具objgraph

        查看内存泄漏

      工具RunSnakeRun:使用图形化分析

    $runsnake result.out

      工具KCachegrind  

    $apt-get install kcachegrind

         工具Meliae

          首先在你的代码中需要导出内存映像的某时刻,输入以下代码

    from meliae import scanner
    scanner.dump_all_objects( filename ) # you can pass a file-handle if you prefer

          然后分析导出的镜像

    $runsnakemem <filename>

      

  • 相关阅读:
    实现mypwd
    2019-2020-2 20175310奚晨妍《网络对抗技术》Exp9 Web安全基础
    2019-2020-2 20175310奚晨妍《网络对抗技术》Exp8 Web基础
    2019-2020-2 20175310奚晨妍《网络对抗技术》Exp7 网络欺诈防范
    2019-2020-2 20175310奚晨妍《网络对抗技术》Exp6 MSF基础应用
    2019-2020-2 20175310奚晨妍《网络对抗技术》Exp5 信息搜集与漏洞扫描
    2019-2020-2 20175310奚晨妍《网络对抗技术》Exp4 恶意代码分析
    2019-2020-2 20175310奚晨妍《网络对抗技术》Exp3 免杀原理与实践
    2019-2020-2 20175310奚晨妍《网络对抗技术》Exp1+ 逆向进阶
    2019-2020-2 20175310奚晨妍《网络对抗技术》Exp2 后门原理与实践
  • 原文地址:https://www.cnblogs.com/yasmi/p/5212378.html
Copyright © 2020-2023  润新知