當(dāng)運(yùn)行一個(gè)復(fù)雜的 Python 程序鹿鳖,它需要很長時(shí)間來執(zhí)行。你或許想提升它的執(zhí)行時(shí)間壮莹。但如何做翅帜?
首先,你需要工具來查明你代碼的瓶頸命满,比如涝滴,那部分執(zhí)行花費(fèi)的時(shí)間長。用這個(gè)方法周荐,你可以首先專注于提升這部分的速度狭莱。
而且,你也應(yīng)該控制內(nèi)存和 CPU 使用率概作,因?yàn)樗梢詾槟阒赋龅拇a可以改進(jìn)的新的部分腋妙。
所以,在本文中讯榕,我將對(duì) 7 個(gè)不同的 Python 工具發(fā)表意見骤素,給你一些關(guān)于你函數(shù)執(zhí)行時(shí)間和內(nèi)存以及** CPU 使用率**的見解。
1. 使用一個(gè)裝飾器來測(cè)量你的函數(shù)
測(cè)量一個(gè)函數(shù)最簡(jiǎn)單的方式就是定義一個(gè)裝飾器來測(cè)量運(yùn)行該函數(shù)的運(yùn)行時(shí)間愚屁,并打印該結(jié)果:
這時(shí)济竹,你已經(jīng)在你想測(cè)量的函數(shù)之前添加了裝飾器,像:
例如霎槐,讓我們測(cè)量下排序一個(gè) 2000000 個(gè)隨機(jī)數(shù)的數(shù)組會(huì)花費(fèi)多長時(shí)間:
如果你運(yùn)行你的腳本送浊,你將看到:
2. 使用 timeit 模塊
另外一個(gè)選項(xiàng)是使用 timeit 模塊,它給你測(cè)量一個(gè)平均時(shí)間丘跌。
為了運(yùn)行它袭景,在你的終端執(zhí)行以下命令:
timing_functions 是你腳本的名字。
在輸出的最后闭树,你會(huì)看到一些像這樣的東西:
表明了運(yùn)行這個(gè)測(cè)試 4 次(-n 4)颊艳,并在每個(gè)測(cè)試中重復(fù)平均 5 次(-r 5)基跑,最佳的結(jié)果是 2.08 秒憨降。
如果你沒有指定測(cè)試或者重復(fù)立帖,它默認(rèn)是 10 次循環(huán)和 5 次重復(fù)。
3. 使用 Uinx 的 time 命令
盡管如此,裝飾器和 timeit 模塊都是基于 Python 的幅疼。這就是為什么 unix time 工具或許有用米奸,因?yàn)樗且粋€(gè)外部的 Python 測(cè)量。
為了運(yùn)行 time 工具類型:
將給出如下輸出:
第一行來自于我們定義的裝飾器衣屏,其他三行是:
1. real 表明了執(zhí)行腳本花費(fèi)的總時(shí)間
2. User 表明了執(zhí)行腳本花費(fèi)在的 CPU 時(shí)間
3. Sys 表明了執(zhí)行腳本花費(fèi)在內(nèi)核函數(shù)的時(shí)間
因此躏升, real time 和 user+sys 相加的不同或許表明了時(shí)間花費(fèi)在等待 I/O 或者是系統(tǒng)在忙于執(zhí)行其他任務(wù)。
4. 使用 cProfile 模塊
如果你想知道花費(fèi)在每個(gè)函數(shù)和方法上的時(shí)間狼忱,以及它們被調(diào)用了多少次膨疏,你可以使用 cProfile 模塊。
現(xiàn)在你將看到你的代碼中每個(gè)函數(shù)被調(diào)用多少次的詳細(xì)描述钻弄,并且它將通過累積花費(fèi)在每個(gè)函數(shù)上面的時(shí)間來排序(感謝 -s cumulative 選項(xiàng))
你將看到花費(fèi)在運(yùn)行你的腳本的總時(shí)間是比以前高的佃却。這是我們測(cè)量每個(gè)函數(shù)執(zhí)行時(shí)間的損失。
5. 使用 line_profiler 模塊
line_profiler 給出了在你代碼每一行花費(fèi)的 CPU 時(shí)間窘俺。
這個(gè)模塊首先應(yīng)該被安裝饲帅,使用命令:
下一步,你需要指定你想使用裝飾器 @profile 評(píng)估哪個(gè)函數(shù)(你不需要把它 import 到你的文件中)瘤泪。
最后灶泵,你可以通過鍵入以下命令取得random_sort2函數(shù)逐行的描述:
-l 標(biāo)識(shí)表明了逐行和 -v 標(biāo)識(shí)表明詳細(xì)輸出。使用這個(gè)方法对途,我們看到了數(shù)組結(jié)構(gòu)花費(fèi)了 44% 的計(jì)算時(shí)間赦邻,sort() 方法花費(fèi)了剩余的 56%。
你也將看到实檀,由于時(shí)間測(cè)量惶洲,這個(gè)腳本執(zhí)行花費(fèi)的或許更長。
6. 使用 memory_profiler 模塊
memory_profiler 模塊被用于在逐行的基礎(chǔ)上膳犹,測(cè)量你代碼的內(nèi)存使用率恬吕。盡管如此,它可能使得你的代碼運(yùn)行的更慢须床。
安裝:
也建議安裝 psutil 包铐料,使得 memory_profile 模塊運(yùn)行的更快:
類似 line_profiler 的方式,使用裝飾器 @profile 來標(biāo)記哪個(gè)函數(shù)被跟蹤豺旬。下一步余赢,鍵入:
是的,前面的腳本比之前的 1 或 2 秒需要更長的時(shí)間哈垢。并且,如果你不安裝 psutil 模塊扛拨,你將一直等待結(jié)果耘分。
看上面的輸出,注意內(nèi)存使用率的單位是 MiB,這代表的是兆字節(jié)(1MiB = 1.05MB)求泰。
7. 使用 guppy 包
最后央渣,使用這個(gè)包,你可以跟蹤每個(gè)類型在你代碼中每個(gè)階段(字符渴频, 元組芽丹, 字典 等等)有多少對(duì)象被創(chuàng)建了。
安裝:
下一步卜朗,像這樣添加到你的代碼中:
并且這樣運(yùn)行你的代碼:
你將看到一些像下面的輸出:
通過配置 heap 在你的代碼的不同地方拔第,你可以在腳本中學(xué)到對(duì)象的創(chuàng)建和銷毀。