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