摘要:有很多性能分析工具,功能強(qiáng)大,可以幫助我們對各種函數(shù)的性能進(jìn)行分析。這篇文章就介紹三種簡單的性能分析工具。小結(jié)本文整理了三個常用的性能分析工具,幫助你定位程序的性能瓶頸。
如果你想優(yōu)化python程序的運(yùn)行效率,你會從哪里下手?
首先,我們要找到「性能瓶頸」,比如哪些函數(shù)的運(yùn)行效率低、計(jì)算時間長,然后分析原因,針對性地進(jìn)行優(yōu)化。
最樸素的方法是,在你預(yù)估的函數(shù)前后加上time.perf_counter()1,然后得出這個函數(shù)的運(yùn)行時間。但這種方法不適用于具有大量函數(shù)調(diào)用的程序。
import timestart = time.perf_counter()func()print("cost %s second" % (time.perf_counter() - start))
python有很多性能分析工具,功能強(qiáng)大,可以幫助我們對各種函數(shù)的性能進(jìn)行分析。
這篇文章就介紹三種簡單的性能分析工具。其中cProfile和timeit都是python標(biāo)準(zhǔn)庫中的工具,無需安裝第三方庫,看完本篇文章,教你快速上手。
推薦指數(shù): ????????
cProfile是python標(biāo)準(zhǔn)庫中一個使用便捷、開銷合理的 C 擴(kuò)展,適用于分析長時間運(yùn)行的程序。2
不想閱讀太多細(xì)節(jié)的小伙伴,可以直接看代碼,非常簡單,直接在cProfile.run中輸入目標(biāo)函數(shù)名稱:
import cProfileimport test_modulecProfile.run("test_module.func()")
在程序運(yùn)行完后,就會在控制臺打印test_module.func()運(yùn)行的具體耗時情況:
538569 function calls (519249 primitive calls) in 71.446 seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 44 0.002 0.000 0.197 0.004 ImageFile.py:154(load) 18 0.000 0.000 0.001 0.000 ImageFile.py:278(load_prepare) 1 0.000 0.000 0.000 0.000 ImageFile.py:30() 1 0.000 0.000 0.000 0.000 ImageFile.py:313(StubImageFile) 1 0.000 0.000 0.000 0.000 ImageFile.py:339(Parser) 13 0.001 0.000 1.348 0.104 ImageFile.py:478(_save)
每一行依次列出了各個子函數(shù)的運(yùn)行分析信息:
ncalls
調(diào)用次數(shù)
tottime
在給定函數(shù)中花費(fèi)的總時間(不包括調(diào)用子函數(shù)的時間)
percall
tottime除以ncalls的商
cumtime
是在這個函數(shù)和所有子函數(shù)中花費(fèi)的累積時間(從調(diào)用到退出)。
percall
是cumtime除以原始調(diào)用次數(shù)的商
filename:lineno(function)
提供每個函數(shù)的各自信息
如果你想保存這些性能數(shù)據(jù),在run函數(shù)的參數(shù)中加上’restats’文件名:
cProfile.run("main()","restats")
就會保存到當(dāng)前目錄下的restats文件中。
加載這些數(shù)據(jù),可以進(jìn)行后續(xù)的比較分析。
import pstatsfrom pstats import SortKey# 加載保存到restats文件中的性能數(shù)據(jù)p = pstats.Stats("restats")# 打印所有統(tǒng)計(jì)信息p.strip_dirs().sort_stats(-1).print_stats()
最常用的是,查看耗時最多的函數(shù)排序,比如前十個:
# 打印累計(jì)耗時最多的10個函數(shù)p.sort_stats(SortKey.CUMULATIVE).print_stats(10)# 打印內(nèi)部耗時最多的10個函數(shù)(不包含子函數(shù))p.sort_stats(SortKey.TIME).print_stats(10)
上面兩個例子分別用到用SortKey.CUMULATIVE
或SortKey.TIME
參數(shù)。
SortKey的具體參數(shù)如下表所示3:
例如,我們在耗時排序中,發(fā)現(xiàn)一些加載函數(shù)的耗時較大,可以多帶帶統(tǒng)計(jì)下包含load的調(diào)用信息:
# 打印包含load的函數(shù)名的調(diào)用者統(tǒng)計(jì)信息p.print_callers(.5, "load")
0.5表示列表被剔除到其原始大小的50%,然后保留包含load的行:
例如,還可以查看哪些類的初始化__init__函數(shù)耗時較多:
# 按耗時排序,依次打印類的__init__方法的統(tǒng)計(jì)信息p.sort_stats(SortKey.CUMULATIVE).print_stats("__init__")
推薦指數(shù): ????
timeit適用于測量小段代碼的耗時,可以在python代碼中調(diào)用,也可以在命令行中調(diào)用4。timeit的設(shè)計(jì)避免了許多用于測量執(zhí)行時間的常見陷阱。
測試你寫的函數(shù)的運(yùn)行時間:
def test(): """Stupid test function""" L = [i for i in range(100)]if __name__ == "__main__": import timeit print(timeit.timeit("test()", setup="from __main__ import test"))
測試一個語句的運(yùn)行時間:
$ python -m timeit "if hasattr(str, "__bool__"): pass"50000 loops, best of 5: 4.26 usec per loop
使用方式:
python -m timeit [-n N] [-r N] [-u U] [-s S] [-h] [statement ...]
-n N, --number=N
執(zhí)行“語句”多少次
-r N, --repeat=N
重復(fù)計(jì)時器多少次(默認(rèn) 5)
-s S, --setup=S
最初執(zhí)行一次的語句(默認(rèn)pass)
-p, --process
測量進(jìn)程時間,而不是掛鐘時間,使用time.process_time() 代替time.perf_counter(),這是默認(rèn)值
3.3 版中的新功能。
-u, --unit=U
指定定時器輸出的時間單位;可以選擇 nsec、usec、msec 或 sec
3.5 版中的新功能。
-v, --verbose
打印原始計(jì)時結(jié)果;重復(fù)以獲得更多數(shù)字精度
-h, --help
打印一個簡短的使用信息并退出
推薦指數(shù): ??????
如果你有IDE,那么很多IDE都提供了性能分析的相關(guān)工具。
以pycharm 專業(yè)版為例,從Run中點(diǎn)擊Profile,即可對當(dāng)前python腳本進(jìn)行性能分析。
程序運(yùn)行結(jié)束后,pycharm會生成以下統(tǒng)計(jì):
這里列出了子函數(shù)的名稱、調(diào)用次數(shù)、耗時等信息,雙擊函數(shù)名可以查看對應(yīng)源碼。
本文整理了三個常用的python性能分析工具,幫助你定位python程序的性能瓶頸。
如果對你有所幫助,歡迎一鍵三連,支持下博主。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/119688.html
Python裝飾器為什么難理解? 無論項(xiàng)目中還是面試都離不開裝飾器話題,裝飾器的強(qiáng)大在于它能夠在不修改原有業(yè)務(wù)邏輯的情況下對代碼進(jìn)行擴(kuò)展,權(quán)限校驗(yàn)、用戶認(rèn)證、日志記錄、性能測試、事務(wù)處理、緩存等都是裝飾器的絕佳應(yīng)用場景,它能夠最大程度地對代碼進(jìn)行復(fù)用。 但為什么初學(xué)者對裝飾器的理解如此困難,我認(rèn)為本質(zhì)上是對Py… Python 實(shí)現(xiàn)車牌定位及分割 作者用 Python 實(shí)現(xiàn)車牌定位及分割的實(shí)踐。 ...
摘要:時間永遠(yuǎn)都過得那么快,一晃從年注冊,到現(xiàn)在已經(jīng)過去了年那些被我藏在收藏夾吃灰的文章,已經(jīng)太多了,是時候把他們整理一下了。那是因?yàn)槭詹貖A太亂,橡皮擦給設(shè)置私密了,不收拾不好看呀。 ...
摘要:致敬首先向偉大的牛人致敬使用狄克斯特拉算法如果所示找出從起點(diǎn)到終點(diǎn)耗時最短的路徑。狄克斯特拉算法思路步驟或思路如下找出最便宜的節(jié)點(diǎn),即可在最短時間內(nèi)前往的節(jié)點(diǎn)。 狄克斯特拉算法是一種實(shí)現(xiàn)了在有障礙物的兩個地點(diǎn)之間找出一條最短路徑的高效算法,解決了機(jī)器人學(xué)中的一個十分關(guān)鍵的問題,即運(yùn)動路徑規(guī)劃問題,至今仍被廣泛應(yīng)用。是貪心方法(greedy method)的一個成功范例。 致敬 首先向偉...
閱讀 2627·2021-11-19 09:56
閱讀 873·2021-09-24 10:25
閱讀 1632·2021-09-09 09:34
閱讀 2194·2021-09-09 09:33
閱讀 1052·2019-08-30 15:54
閱讀 541·2019-08-29 18:33
閱讀 1264·2019-08-29 17:19
閱讀 505·2019-08-29 14:19