8個核心編碼技巧,可實現更快的python運行速度

原文來自外文:翻譯python

前言linux

總的來講,人們使用python是由於它方便且易於編程,而不是由於它很快。大量的第三方庫和對Python的工業支持的普遍性彌補了它沒有Java或C的原始性能。開發速度優先於執行速度。程序員

但在許多狀況下,它沒必要是一個非此即彼的命題。適當地優化,Python應用程序能夠以驚人的速度運行——也許不是Java或C快,但對於Web應用程序、數據分析、管理和自動化工具以及其餘大多數目的來講都足夠快。實際上,您可能會忘記您是在用應用程序性能來換取開發人員的生產力。算法

優化python性能並不能歸結爲任何一個因素。相反,它是關於應用全部可用的最佳實踐,並選擇最適合當前場景的最佳實踐。(Dropbox中的人們有一個關於Python優化功能最引人注目的例子。)編程

在這篇文章中,我將概述許多常見的Python優化。其中一些是隻需將一個項目切換到另外一個項目(如更改python解釋器)便可實現的嵌入式度量,但實現最大回報的項目將須要更詳細的工做。windows

 

1。Memoize(緩存)重複使用的數據數組

當你能作到一次並保存結果時,千萬不要作一千次工做。若是有一個常常調用的函數返回可預測的結果,那麼python爲您提供了將結果緩存到內存中的選項。返回相同結果的後續調用幾乎會當即返回。緩存

各類各樣的例子展現瞭如何作到這一點;我最喜歡的記憶幾乎是最少的。python的一個本機庫functools具備@functools.lru緩存裝飾器,它緩存最近對函數的n個調用。當正在緩存的值發生變化,但在特定的時間窗口內是相對靜態的時,這很方便。一天中最新使用的項目列表就是一個很好的例子。服務器

2。將數學移動到numpy數據結構

若是您正在進行基於矩陣或數組的數學運算,而且不但願Python解釋器妨礙您的工做,請使用numpy。經過利用C庫進行繁重的工做,numpy提供了比本機python更快的數組處理。它還比Python的內置數據結構更有效地存儲數字數據。

相對來講,非異類的數學也能夠被numpy大大加快。該包爲許多常見的python數學操做(如min和max)提供了替換,這些操做的速度比原來的python快不少倍。

numpy的另外一個好處是更有效地使用大型對象的內存,好比擁有數百萬個項目的列表。通常來講,像numpy中那樣的大型對象若是用傳統的python來表示,則佔用大約四分之一的內存。請注意,它有助於從做業的正確數據結構開始,即優化自己。

重寫python算法以使用numpy須要一些工做,由於數組對象須要使用numpy的語法聲明。可是numpy在實際的數學運算中使用了python現有的習語(+、-,等等),因此從長遠來看,切換到numpy並不會太使人迷惑。

3。使用C庫

numpy使用C語言編寫的庫是一種很好的模擬策略。若是有一個現有的C庫能夠知足您的須要,那麼Python及其生態系統提供了幾個選項來鏈接到該庫並利用其速度。

最多見的方法是使用Python的CTypes庫。由於ctypes與其餘python應用程序(和運行時)普遍兼容,因此它是最佳的開始位置,但它遠不是鎮上惟一的遊戲。cffi項目爲c.cython提供了一個更優雅的接口(見下文),也能夠用來包裝外部庫,儘管代價是必須學習cython的標記。

 

學習歷來不是一我的的事情,要有個相互監督的夥伴,工做須要學習python或者有興趣學習python的夥伴能夠私信回覆小編「學習」 獲取資料,一塊兒學習

4。與多處理並行

傳統的python應用程序——那些在cpython中實現的應用程序——一次只執行一個線程,以免在使用多個線程時出現狀態問題。這是臭名昭著的全球口譯員鎖(gil)。它的存在有充分的理由,這並無使它變得更加華麗。

隨着時間的推移,gil的效率顯著提升(運行python 3而不是python 2的另外一個緣由),但核心問題仍然存在。一個cpython應用程序能夠是多線程的,可是cpython不容許這些線程在多個核心上並行運行。

爲了解決這個問題,python提供了多處理模塊來在不一樣的核心上運行python解釋器的多個實例。狀態能夠經過共享內存或服務器進程來共享,數據能夠經過隊列或管道在進程實例之間傳遞。

您仍然須要在進程之間手動管理狀態。另外,在啓動多個Python實例並在其中傳遞對象的過程當中,不會有太多的開銷。可是對於長期運行的進程來講,多處理庫是很是有用的,由於它能夠從跨核心的並行性中獲益。

另外,使用C庫的python模塊和包(如numpy)徹底避免使用gil。這也是他們被推薦提速的另外一個緣由。

5。知道你的庫在作什麼

簡單地輸入XYZ並利用無數其餘程序員的工做是多麼方便!可是您須要知道,第三方庫能夠改變應用程序的性能,而不是老是爲了更好。

有時,這以明顯的方式表現出來,例如當來自特定庫的模塊構成瓶頸時。(再次強調,剖析會有所幫助。)有時狀況不那麼明顯。示例:Pyglet是一個用於建立窗口化圖形應用程序的簡便庫,它自動啓用調試模式,這會顯著影響性能,直到顯式禁用它爲止。除非您閱讀文檔,不然您可能永遠不會意識到這一點。閱讀並被告知。

6。注意平臺

python運行跨平臺,但這並不意味着每一個操做系統(windows、linux、os x)的特性都是在python下抽象出來的。大多數時候,這意味着要了解平臺的具體狀況,好比路徑命名約定,對於這些約定,有助手函數。

但在性能方面,瞭解平臺差別也很重要。例如,在Windows上,須要計時器精度小於15毫秒(例如,對於多媒體)的python腳本將須要使用Windows API調用來訪問高分辨率計時器或提升計時器分辨率。

7。與PyPy同行

cpython是Python最經常使用的實現,它將兼容性優先於原始速度。對於那些想把速度放在首位的程序員來講,有pypy,一個配備了jit編譯器的python實現來加速代碼執行。

由於pypy是做爲cpython的替代品而設計的,因此它是快速提升性能的最簡單方法之一。許多常見的python應用程序將在pypy上運行。通常來講,應用程序越依賴於「普通」的python,就越有可能在pypy上運行而不進行修改。

然而,充分利用PYPY可能須要測試和研究。您會發現長時間運行的應用程序從Pypy得到最大的性能收益,由於編譯器會分析一段時間後的執行狀況。對於運行和退出的短腳本,您最好使用cpython,由於性能提高不足以克服JIT的開銷。

請注意,pypy對python 3的支持仍然落後於幾個版本;它目前支持python 3.2.5。使用最新的python特性(如async和await-co例程)的代碼將沒法工做。最後,使用ctypes的python應用程序的行爲可能並不老是如預期的那樣。若是您正在編寫可能同時在pypy和cpython上運行的東西,那麼爲每一個解釋器分別處理用例多是有意義的。

其餘經過抖動加速python的實驗仍在取得成果。其中包括一個微軟項目pyjion,它爲cpython提供了一個JIT接口。微軟提供了本身的JIT做爲概念證實。

 

8。升級至python 3

若是您使用的是python 2.x,而且沒有覆蓋的緣由(好比不兼容的模塊)來堅持使用它,那麼您應該跳到python 3。

除了python 3做爲語言的將來,python 3中還提供了許多構造和優化,而python 2.x中沒有這些構造和優化。例如,python 3.5經過將async和wait關鍵字做爲語言語法的一部分來減小異步編程的麻煩。python 3.2對全局解釋器鎖進行了重大升級,顯著改進了python處理多個線程的方式。

相關文章
相關標籤/搜索