1、優(yōu)化算法時間
算法的時間復雜度對程序的執(zhí)行效率影響最大,在 Python 中可以通過選擇合適的數(shù)據(jù)結(jié)構(gòu)來優(yōu)化時間復雜度,如 list 和 set 查找某一個元素的時間復雜度分別是 O(n)和 O(1)。不同的場景有不同的優(yōu)化方式,總得來說,一般有分治,分支界限,貪心,動態(tài)規(guī)劃等思想。
2、循環(huán)優(yōu)化
每種編程語言都會強調(diào)需要優(yōu)化循環(huán)。當使用 Python 的時候,你可以依靠大量的技巧使得循環(huán)運行得更快。然而,開發(fā)者經(jīng)常漏掉的一個方法是:
避免在一個循環(huán)中使用點操作。每一次你調(diào)用方法 str.upper,Python 都會求該方法的值。然而,如果你用一個變量代替求得的值,值就變成了已知的,Python 就可以更快地執(zhí)行任務。優(yōu)化循環(huán)的關(guān)鍵,是要減少 Python 在循環(huán)內(nèi)部執(zhí)行的工作量,因為 Python 原生的解釋器在那種情況下,真的會減緩執(zhí)行的速度。(注意:優(yōu)化循環(huán)的方法有很多,這只是其中的一個。例如,許多程序員都會說,列表推導是在循環(huán)中提高執(zhí)行速度的最好方式。這里的關(guān)鍵是,優(yōu)化循環(huán)是程序取得更高的執(zhí)行速度的更好方式之一。)
3、函數(shù)選擇
在循環(huán)的時候使用 xrange 而不是 range;使用 xrange 可以節(jié)省大量的系統(tǒng)內(nèi)存,因為 xrange() 在序列中每次調(diào)用只產(chǎn)生一個整數(shù)元素。而 range()將直接返回完整的元素列表,用于循環(huán)時會有不必要的開銷。在 python3 中 xrange 不再存在,里面 range 提供一個可以遍歷任意長度的范圍的 iterator。
4、并行編程
因為 GIL 的存在,Python 很難充分利用多核 CPU 的優(yōu)勢。但是,可以通過內(nèi)置的模 multiprocessing 實現(xiàn)下面幾種并行模式:
多進程:對于 CPU 密集型的程序,可以使用 multiprocessing 的 Process,Pool 等封裝好的類,通過多進程的方式實現(xiàn)并行計算。但是因為進程中的通信成本比較大,對于進程之間需要大量數(shù)據(jù)交互的程序效率未必有大的提高。
多線程:對于 IO 密集型的程序,multiprocessing.dummy 模塊使用 multiprocessing 的接口封裝 threading,使得多線程編程也變得非常輕松(比如可以使用 Pool 的 map 接口,簡潔高效)。
布式:multiprocessing 中的 Managers 類提供了可以在不同進程之共享數(shù)據(jù)的方式,可以在此基礎(chǔ)上開發(fā)出分布式的程序。
不同的業(yè)務場景可以選擇其中的一種或幾種的組合實現(xiàn)程序性能的優(yōu)化。
5、使用性能分析工具
除了上面在 ipython 使用到的 timeit 模塊,還有 cProfile。cProfile 的使用方式也非常簡單:python-mcProfilefilename.py,filename.py 是要運行程序的文件名,可以在標準輸出中看到每一個函數(shù)被調(diào)用的次數(shù)和運行的時間,從而找到程序的性能瓶頸,然后可以有針對性地優(yōu)化。
6、set 的用法
set 的 union,intersection,difference 操作要比 list 的迭代要快。因此如果涉及到求 list 交集,并集或者差的問題可以轉(zhuǎn)換為 set 來操作。
7、PyPy
PyPy 是用 RPython(CPython 的子集)實現(xiàn)的 Python,根據(jù)官網(wǎng)的基準測試數(shù)據(jù),它比 CPython 實現(xiàn)的 Python 要快 6 倍以上??斓脑蚴鞘褂昧?Just-in-Time(JIT)編譯器,即動態(tài)編譯器,與靜態(tài)編譯器(如 gcc,javac 等)不同,它是利用程序運行的過程的數(shù)據(jù)進行優(yōu)化。由于歷史原因,目前 pypy 中還保留著 GIL,不過正在進行的 STM 項目試圖將 PyPy 變成沒有 GIL 的 Python。如果 python 程序中含有 C 擴展(非 cffi 的方式),JIT 的優(yōu)化效果會大打折扣,甚至比 CPython 慢(比 Numpy)。
所以在 PyPy 中最好用純 Python 或使用 cffi 擴展。