• Performance tuning in Python


    组内同事下午做了个关于python的小的share,觉得讲的还不错,将其中的Performance Tuning部分摘抄出来,供参考。

    首先,谨记高德纳老先生的名言:过早优化是万恶之源(Premature optimization is the root of all evil.)

    性能调优分问如下几步:

    1. Find bottlenecks
    2. Use better algorithms
    3. Use faster tools
    4. Write optimized code
    5. Write your own python module
    6. Parallezie the compution

    第一步是找出程序运行的性能瓶颈所在。python里提供了相应的工具,如Profile和cProfile。

    这里先给出一份描述更详尽的文章:关于Python Profiles性能分析器http://kb.cnblogs.com/a/2337112/

    Profile是一个纯的python模块,而cProfile是用C语言写的一个python拓展。这里使用cProfile。

    (注:cProfile可能需要自行安装sudo apt-get install python-profiler)。

    给出一个待分析的程序profiler_demo.py:

     1 #!/usr/bin/env python
     2 
     3 above_limit = 10000001
     4 def func1():
     5     s = 0
     6     for i in xrange(above_limit):
     7         s += i
     8 
     9 def func2():
    10     s = sum(range(above_limit))
    11 
    12 def func3():
    13     s = sum(xrange(above_limit))
    14 
    15 func1()
    16 func2()
    17 func3()

    在命令行执行python -m cProfile profiler_demo.py ,即可在运行程序的同时,得出程序的性能分析结果。

    liuhao@liuhao-Lenovo:~/program/python$ python -m cProfile profiler_demo.py 
             8 function calls in 1.083 CPU seconds
    
       Ordered by: standard name
    
       ncalls  tottime  percall  cumtime  percall filename:lineno(function)
            1    0.000    0.000    0.101    0.101 profiler_demo.py:12(func3)
            1    0.000    0.000    1.083    1.083 profiler_demo.py:3(<module>)
            1    0.377    0.377    0.377    0.377 profiler_demo.py:4(func1)
            1    0.153    0.153    0.604    0.604 profiler_demo.py:9(func2)
            1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
            1    0.289    0.289    0.289    0.289 {range}
            2    0.263    0.131    0.263    0.131 {sum}

    对结果进行简单说明:

    1.从第一行可以看出,此Python脚本共包括8个函数调用,一共花费的CPU时间为1.083秒;

    2.ncalls为函数调用次数,tottime为函数本身不包含调用其他函数的执行时间,cumtime为总体函数的调用执行时间;

    3.cProfiler是基于lsprof的,从输出中标红的部分也可以看到;

    4.按照结果,我们知道func3是执行最快的;

    第二步,是选用更好的算法,在数据规模很大的时候,能够使用O(NlogN)的算法,就不要选用O(N^2)的算法;能够用(1+100)*100/2,就不要用sum(xrange(101));

    这里再给出一个使用Python提供的Decorator,利用空间换时间,计算Fibonacci数列的例子:

    程序如下:

     1 def fib_nocache(n):
     2     if n == 0 or n == 1:
     3         return 1
     4     return fib_nocache(n-2) + fib_nocache(n-1)
     5 
     6 def cache(func):
     7     c = {}
     8     def _(n):
     9         r = c.get(n)
    10         if r is None:
    11             r = c[n] = func(n)
    12         return r
    13     return _
    14 
    15 @cache
    16 def fib_cache(n):
    17     if n == 0 or n == 1:
    18         return 1
    19     return fib_cache(n-2) + fib_cache(n-1)
    20        
    21 fib_nocache(32)
    22 fib_cache(32)

    性能分析结果如下:

             7049317 function calls (69 primitive calls) in 2.305 CPU seconds
    
       Ordered by: standard name
    
       ncalls  tottime  percall  cumtime  percall filename:lineno(function)
            1    0.000    0.000    2.305    2.305 profiler_fib.py:1(<module>)
    7049155/1    2.305    0.000    2.305    2.305 profiler_fib.py:1(fib_nocache)
         33/1    0.000    0.000    0.000    0.000 profiler_fib.py:15(fib_cache)
            1    0.000    0.000    0.000    0.000 profiler_fib.py:6(cache)
         63/1    0.000    0.000    0.000    0.000 profiler_fib.py:8(_)
            1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
           63    0.000    0.000    0.000    0.000 {method 'get' of 'dict' objects}

    之前没有接触过Decorator,看到类似的写法还是蛮受用的。

    第三步,使用更好的工具。这里主要指Python中的一些惯用法,比如:

    1. xrange()比range()更快;
    2. itertools.imap()比map()更快;
    3. dict.iteritems()比dict.items更快;
    4. for i, item in enumerate(seq)比 for i in range(len(seq))更快;
    5. etc

    第四步,写更好的代码,将好的算法和好的工具结合到一块;

    第五步和第六步,一个是将关键的模块用C来重写,一个是将原本串行的程序改成并行执行,都值得再单独写一篇博客,以后有空再慢慢写吧。

  • 相关阅读:
    解决tomcat启东时一闪而过的问题
    如果数据库中的时间类型与mybatis的时间类型对应关系
    el 表达式中某一项过长时需要截取字符串长度,当悬停的时候显示全部内容
    ubuntu/linux系统中安装jdk以及eclipse(附图解详细步骤)
    Unity利用SMSSDK实现短信验证码(附代码)
    Unity利用Share SDK实现QQ、微信及微博第三方登录及定制内容分享(附代码)
    Unity编辑器扩展
    VR中射线点击按钮的实现
    Unity中几个特殊路径在各个平台的访问方式
    多态
  • 原文地址:https://www.cnblogs.com/liuhao/p/2612188.html
Copyright © 2020-2023  润新知