7個Python性能優化工具

雖然Python是一個”慢慢的“語言,但是不代表我們對性能沒有任何的追求,在程序運行過程中,如果發現程序運行時間太長或者內存佔用過大,免不了需要對程序的執行過程進行一些監測,找到有問題的地方,進行優化。今天來分享一些平時用到的Python性能分析工具

memory_profiler

memory_profiler是監控python進程的神器,只需要在函數加一個裝飾器就可以輸出每行代碼的內存使用情況

安裝:

pip install memory_profiler

使用:

import time

@profile
def my_func():
    a = [1] * (10 ** 6)
    b = [2] * (2 * 10 ** 7)
    time.sleep(10)
    del b
    del a
    print "+++++++++"

if __name__ == '__main__':
    my_func()

輸出:

$ python -m memory_profiler del3.py
+++++++++
Filename: del3.py

Line #    Mem usage    Increment   Line Contents
================================================
  10.293 MiB    0.000 MiB   @profile
                            def my_func():
  17.934 MiB    7.641 MiB       a = [1] * (10 ** 6)
 170.523 MiB  152.590 MiB       b = [2] * (2 * 10 ** 7)
 170.527 MiB    0.004 MiB       time.sleep(10)
  17.938 MiB -152.590 MiB       del b
  10.305 MiB   -7.633 MiB       del a
  10.309 MiB    0.004 MiB       print "+++++++++"

內建函數 timeit

import timeit
import time

def my_func():
    time.sleep(1)
    return sum([1,2,3])

result = timeit.timeit(my_func, number=5)
print(result)

Jupyter Notebook Magic 命令

在Jupyter Notebook中,可以通過%%timeit魔法命令測試cell中代碼的運行時間

%%timeit

import time
def my_func():
    time.sleep(1)
    return sum([1,2,3])

result = timeit.timeit(my_func, number=5)
print(result)

計時裝飾器

Python 中的裝飾器可以在其他函數不需要改動任何代碼的情況下增加額外功能,經常用在,插入日誌、性能測試、權限校驗等場景中。我們可以將計時功能封裝成一個裝飾器,方便複用。

from functools import wraps
import time

def timeit(func):
    @wraps(func)
    def deco():
        start = time.time()
        res = func()
        end = time.time()
        delta = end - start
        print("Wall time ", delta)
        return res
    return deco

使用:

@timeit
def my_func():
    # do something
    time.sleep(3)
    pass

輸出:

Wall time: 3

line_profiler

如果我們除了想知道代碼整體的運行時間之外,還要精確分析每行代碼的運行時間,那python的 line_profiler 模塊就可以幫到你啦!line_profiler 可以用來測試函數每行代碼的響應時間等情況。爲了使用方便,可以將line_profiler 相關函數封裝在裝飾器中進行使用,這樣在接口請求時,則會執行此裝飾器並打印出結果。

安裝:

pip install line_profiler

使用:

from flask import Flask, jsonify
import time
from functools import wraps
from line_profiler import LineProfiler

# 查詢接口中每行代碼執行的時間
def func_line_time(f):
    @wraps(f)
    def decorator(*args, **kwargs):
        func_return = f(*args, **kwargs)
        lp = LineProfiler()
        lp_wrap = lp(f)
        lp_wrap(*args, **kwargs) 
        lp.print_stats() 
        return func_return 
    return decorator

app = Flask(__name__)

@app.route('/line_test') 
@func_line_time 
def line_test(): 
    for item in range(5): 
        time.sleep(1) 
    for item in xrange(5): 
        time.sleep(0.5) 
    return jsonify({'code':200})

  
if __name__=='__main__': 
app.run()

輸出:

* Running on http://127.0.0.1:5000/
Timer unit: 1e-06 s

Total time: 7.50827 s
File: /home/rgc/baidu_eye/carrier/test/flask_line_profiler_test.py
Function: line_test at line 22

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
                                          @app.route('/line_test')
                                          @func_line_time
                                          def line_test():
        6         33.0      5.5      0.0      for item in range(5):
        5    5005225.0 1001045.0     66.7          time.sleep(1)
        6         31.0      5.2      0.0      for item in xrange(5):
        5    2502696.0 500539.2     33.3          time.sleep(0.5)
        1        282.0    282.0      0.0      return jsonify({'code':200})

127.0.0.1 - - [05/Mar/2018 15:58:21] "GET /line_test HTTP/1.1" 200 -

pyheat

相較於上面的代碼運行時間測試工具,pyheat 通過matplotlib 的繪製熱力圖來展現代碼的運行時間,顯得更爲直觀
在這裏插入圖片描述

安裝:

pip install py-heat

使用方法:

pyheat <path_to_python_file> --out image_file.png

heartrate

heartrate 也是一個可視化的監測工具,可以像監測心率一樣追蹤程序運行,通過web頁面可視化Python程序的執行過程。
img
左側數字表示每行代碼被觸發的次數。長方框表示最近被觸發的代碼行——方框越長表示觸發次數越多,顏色越淺表示最近被觸發次數越多。該工具記錄的是每行代碼執行的次數,

而不是具體執行時間,在性能調試的時候有些雞肋

安裝:

pip install --user heartrate

使用:

import heartrate
from heartrate import trace, files

heartrate.trace(browser=True)
trace(files=files.path_contains('my_app', 'my_library'))

ref: 原文來自於微信公衆號

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章