Python 做效能分析(Profiling)的兩個方式

其實網路上相關的教學很多,這邊簡單記下兩個最簡單的方式,大部分的 case 都可通用。

如果想要詳細一點的,可以參考良葛格在 CodeData 上面的這篇文章:Python Tutorial 第六堂(2)效能評測、PyCon Taiwan

timeit 模組

這個模組的優點是可以用來計算確定範圍的時間,比較命令式的 script 可以用這個來確認某段 code 跑了多久。

我的用法主要是像這樣:

#!/usr/bin/env python

import timeit

timer_start = timeit.default_timer()
# ...do something

timer_end = timeit.default_timer()

print timer_end - timer_start

你就會看到你這段程式執行了多少秒了,覺得單位太小的可以自己乘上 1000。

cProfile 模組

這個模組比較適合 functional 一點的程式架構,因爲他的 profiling 是 function based 的,你可以看到所有的 function call 的一些資訊:

  • 被 call 了幾次
  • 單次 call 裏面運行的時間
  • 全部 call 運行的時間

只要是 function,不管 named function 或是 lambda function 都會被計算進去,假如你寫程式寫得很 functional 的狀況下很好用。

用法有兩種:從 Command-line 直接執行,在程式碼中插入。

** 從 Command-line 直接執行 **

python -m cProfile yourprogram.py

** 在程式碼中插入

如果你的程式本來長這樣,

functionToProfile(a, b, c, d)

你就可以把它換成這樣執行,

import cProfile

cProfile.run('functionToProfile(a, b, c, d)')

他的輸出格式會長這樣:

     18184 function calls in 0.969 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
 3916    0.004    0.000    0.004    0.000 main.py:10(rate)
    1    0.009    0.009    0.963    0.963 main.py:18(collect_rates)
    1    0.003    0.003    0.969    0.969 main.py:2(<module>)
    1    0.947    0.947    0.948    0.948 main.py:31(do_check)
    1    0.001    0.001    0.964    0.964 main.py:53(do)
    1    0.000    0.000    0.000    0.000 main.py:56(transform_back)
    1    0.000    0.000    0.000    0.000 main.py:59(Point)
    1    0.000    0.000    0.000    0.000 main.py:6(transform)
  132    0.000    0.000    0.000    0.000 main.py:60(__init__)
    1    0.000    0.000    0.000    0.000 pprint.py:35(<module>)
    1    0.000    0.000    0.000    0.000 pprint.py:84(PrettyPrinter)
    1    0.000    0.000    0.000    0.000 timeit.py:105(Timer)
    1    0.001    0.001    0.001    0.001 timeit.py:53(<module>)
 2343    0.000    0.000    0.000    0.000 {len}
   22    0.000    0.000    0.000    0.000 {max}
11748    0.003    0.000    0.003    0.000 {method 'add' of 'set' objects}
    1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
   11    0.000    0.000    0.000    0.000 {method 'values' of 'dict' objects}
comments powered by Disqus