官术网_书友最值得收藏!

2.1 高效地剖析

剖析的首要目標(biāo)是對有代表性的系統(tǒng)進(jìn)行測試,找出速度緩慢(或占用RAM過多、導(dǎo)致大量磁盤I/O或網(wǎng)絡(luò)I/O)的部分。剖析通常會(huì)帶來額外的開銷(通常可能導(dǎo)致速度變?yōu)樵瓉淼?/100~1/10),而你希望在盡可能接近實(shí)際情況的環(huán)境中運(yùn)行代碼。因此,你需要提取測試用例,并將要測試的系統(tǒng)部分隔離——最理想的情況是它位于一組獨(dú)立的模塊中。

本章首先介紹最基本的剖析方法,這包括IPython命令%timeit、函數(shù)time.time()以及計(jì)時(shí)裝飾器。你可以使用這些方法來搞清楚語句和函數(shù)的行為。

然后,本章介紹了cProfile(見2.6節(jié)),演示了如何使用內(nèi)置工具cProfile來搞清楚代碼中哪些函數(shù)耗時(shí)最長。這讓你能夠?qū)栴}有大致認(rèn)識,進(jìn)而專注于那些關(guān)鍵函數(shù)。

接下來,本章介紹line_profiler(見2.8節(jié)),line_profiler讓你能夠逐行剖析選定的函數(shù),結(jié)果包括每行的執(zhí)行次數(shù)及時(shí)間占比,這些信息讓你能夠知道哪些代碼運(yùn)行緩慢以及其中的原因。

有了line_profiler的結(jié)果后,你就掌握了接著使用編譯器所需的信息(見第7章)。

在第6章,你將學(xué)習(xí)如何使用perf stat來搞明白以下兩個(gè)方面:最終在CPU中執(zhí)行了多少個(gè)指令;CPU緩存的利用情況。這讓你能夠?qū)仃囘\(yùn)算進(jìn)行高級優(yōu)化。閱讀完本章后,你就應(yīng)該去看看示例6-8。

如果要優(yōu)化的是長期運(yùn)行的系統(tǒng),則使用line_profiler進(jìn)行剖析后,你還可能想使用py-spy來了解正在運(yùn)行的Python進(jìn)程。

為幫助你搞明白RAM占用量高的原因,我們將演示memory_profiler(見2.9節(jié))。它特別適用于在帶標(biāo)注的圖表中跟蹤一段時(shí)間內(nèi)RAM的占用量,讓你能夠向同事解釋有些函數(shù)的RAM占用量超過預(yù)期的原因。

警告:不管使用哪種代碼剖析方法,都別忘了單元測試的代碼覆蓋率必須足夠高。單元測試有助于避免愚蠢的錯(cuò)誤、確保結(jié)果可重現(xiàn)。沒有單元測試,你將身處險(xiǎn)境。

務(wù)必先對代碼進(jìn)行剖析,再編譯或重寫算法,因?yàn)橐_定提高代碼速度的最有效方式,必須有理有據(jù)。

接下來,本章將介紹CPython中的Python字節(jié)碼(見2.11.1節(jié)),這讓你能夠知道幕后發(fā)生的事情。具體地說,知道基于棧的Python虛擬機(jī)的工作原理后,有助于你明白為何有些編碼方式的運(yùn)行速度比其他方式要慢。

然后本章將復(fù)習(xí)如何在剖析過程中結(jié)合使用單元測試,在提高代碼運(yùn)行效率的同時(shí)確保它們正確無誤(見2.12節(jié))。

最后,本章將討論剖析策略(見2.13節(jié)),讓你能夠可靠地剖析代碼,并收集驗(yàn)證假設(shè)所需的正確數(shù)據(jù)。屆時(shí)你將了解到,動(dòng)態(tài)CPU頻率縮放(CPU frequency scaling)以及諸如Turbo Boost等特性可能導(dǎo)致剖析結(jié)果不準(zhǔn)確,因此你將學(xué)習(xí)如何禁用它們。

為演示前述各種剖析步驟,我們需要一個(gè)易于分析的函數(shù)。2.2節(jié)將介紹朱利亞集合,這是一個(gè)內(nèi)存占用量較高的CPU密集型函數(shù),它還具有非線性特征(即結(jié)果難以預(yù)測),這意味著需要在運(yùn)行時(shí)進(jìn)行剖析,而無法做離線分析。

主站蜘蛛池模板: 泗阳县| 体育| 子洲县| 屯门区| 泰安市| 车致| 南澳县| 民权县| 太原市| 德阳市| 贵港市| 肥东县| 平阴县| 弥渡县| 手游| 碌曲县| 桃江县| 望城县| 临泉县| 扎囊县| 名山县| 永年县| 崇左市| 祥云县| 旬邑县| 桦甸市| 沾化县| 朝阳市| 兴城市| 宣化县| 阳曲县| 临海市| 楚雄市| 盈江县| 阳春市| 安多县| 临江市| 张家界市| 武乡县| 台北市| 淅川县|