究竟哪個版本的Python是最快的?
Python 3 比 Python 2 慢嗎?哪個版本的 Python 3 速度最快?還有哪些措施可以提高速度?究竟哪個版本的 Python 是最快的?當然,“這取決于”多種因素,但它具體取決于什么,我們應當如何為自己的應用程序找到最快的 Python 版本呢?就這些問題,今天我來試著做一些測試。
使用 Python 性能測試程序
我之前在 speed.python.org 網站上提到過,Python 核心團隊非常關心性能,這對于比較 CPython 版本的“官方”基準測試非常有用。
但是這個測試依然存在一些問題:
- 測試結果不易理解
- 測試不包括 PyPy
首先,執行指令 pip install performance 來 下載測試程序,然后執行以下指令:
pyperformance run --python={chosen_python_runtime} -o my_results.json
該指令將針對 Python 的目標版本多次運行一系列“真實”應用的測試程序,并記錄測試結果的平均值。
在本文中,我主要對以下版本的 Python 進行了測試:
- 2.7.10,
- 3.4.4,
- 3.5.4,
- 3.6.1,
- 3.7(beta 2)。
此外,還測試了 PyPy(5.6)和 PyPy3(5.4.10)。
測試結果
我已經根據這套測試用例進行了測試,大家可以查看測試結果。當然,你也可以編寫自己的測試用例并運行自己的測試。
我還編寫了一個簡單的腳本,用來獲取性能數據文件列表,并為每個測試結果制作了非常直觀的圖表。我將這個腳本的代碼放在了 GitHub 上(見文末鏈接)。
在所有圖表中,結果都以秒為單位,數值越低說明性能越好。
關于完整的測試結果和圖表,可以查看以下鏈接:
https://github.com/tonybaloney/performance_testing/tree/master/png
我認為很重要的測試都包含在其中了。其余的測試與已經進行的測試大同小異,已經包含在結論中了。
渲染 HTML 模板
django_html 測試將使用 Django 模板渲染引擎創建一個 150 行×150 列的 HTML 表格。它利用了 Django 引擎的內容和模板類。
Python 3.7 的速度 比 Python 2.7 快 1.19 倍,但是除了 Python3.7 之外,其他版本的 Python3 都比 Python 2.7 慢。該結果與 speed.python.org 網站的測試結果一致。
PyPy 的測試結果顯示,其運行速度比任何一個 CPython 的 Python 版本都快得多,而 PyPy3 則會比 PyPy 慢兩倍。需要注意的是,Django 最近決定在 Django 2.0 及更高版本中將放棄對 Python 2 的支持,這意味著 PyPy 將不再與 Django 2 兼容。
啟動時間
該測試主要用來測試 Python 解釋器啟動所花費的時間。如果你打算運行多個進程來打破 Python 的“GIL”約束,那么這將是非常重要的。
此處我先跳過 PyPy,尤其是 PyPy3,我會在文章末尾再進行探討。
從上圖可見,Python 2.7 的啟動時間是最短的。
加密測試:crypto_paes
在加密測試中,你會發現 Python 2 相比 Python 3 的速度明顯快得多。什么原因呢?因為加密需要大量的數字運算,而 Python 3 廢棄了 32 位整型,取而代之的是長整型。
對于 PyPy 用戶來說,你應該會注意到 PyPy3 比 PyPy 慢 5 倍!
算法測試:n-queens
這個算法可能不會讓所有人都舒心,用這個算法來進行測試,可能會勾起一些人當初在算法課上經歷的不美好回憶,對此我只能說抱歉了。這個算法的規則實際上很簡單,就是把 n 個“皇后”放在棋盤上,保證任意兩個“皇后”都不在同一行、同一列或者同一斜線上,使她們攻擊不到彼此。
在 CPython 系列中,Python3.7 的性能再次奪魁。此外,PyPy 和 PyPy3 的測試結果非常相似。
浮點運算
在浮點運算的測試中,我將人為地通過 math.cos(),math.sin() 和 math.sqrt() 函數創建繁重的浮點運算應用程序,總共創建 10 萬個浮點對象。
從測試結果可以看出,PyPy 非常適合浮點運算,對于大量的數據處理、可預測的類型和方法以及循環,PyPy 展現出了杰出的性能。由于 Python 3.7 具有新的快速方法調用操作碼,因此在 CPython 中,它的速度最快。
正則表達式
在正則表達式測試中,“我使用了網絡上最流行的 50 個網頁,并記錄所有正則表達式操作。每個操作都有一個權重,它根據頁面出現的熱門程度以及加載每個頁面時執行的次數計算得來。最后,使用 ROT13 對數據中的字母進行編碼,這樣不會影響正則表達式匹配其輸入的方式。”
在這個測試中,我不知道 PyPy 出了什么問題,我很想知道其他人是否得到相同的結果!
Python 3 比 Python 2 更快嗎?
是的! 在大多數測試中,Python3 都比 Python2 更快。但有幾個例外情況值得注意,在加密測試中,由于整型數據類型的原因,Python 3 的速度比 Python2 慢了 1.35 倍,在啟動時間測試中,Python3 則比 Python2 慢了 1.39 倍。
Python 3 啟動慢的問題將會是 CPython 核心團隊在 3.8 和 3.9 版本中主要解決的問題之一。
除了加密和啟動時間測試之外,在其他的測試項目中,Python 3 的速度比 Python2 大約快 1.2-1.3 倍。改進后的 Python 3.7 升級版將會在今年年底面世。
既然 PyPy 快得多,為什么不是所有人都使用它呢?
PyPy 擁有即時(JIT)編譯器,因此它比 CPython 快。JIT 編譯器具有很大的好處,因為它們在執行可預測的重復性任務時非常高效。Python 性能測試的其中一個特點是,你需要多次運行同一段代碼以使其準確無誤,從而減少應用程序的錯誤邊界。因此,PyPy 面對這樣的測試性能更優。
JIT 編譯器,尤其是 PyPy 的 JIT 編譯器最顯著的缺點是啟動成本高。另一個缺點是許多 C 語言擴展程序缺乏兼容性。因為“Python”(CPython,官方的 PSF Python)是用 C 語言編寫的,PyPi 上的許多第三方擴展利用了這一點。Numpy 就是一個很好的例子,Numpy 的大部分代碼都是用優化的 C 代碼編寫的。當你執行 pip install numpy 命令時,它會使用本地 C 編譯器為你的 Python 運行時建立一個二進制庫,供 Python 程序使用。
由于 PyPy 是用 Python 編寫的,很多模塊根本無法在 PyPy 中工作,所以你需要經常進行檢查。
此外,PyPy 也需要面對與 CPython 相同的挑戰:從 Python2 向 Python3 轉變。直到最近我仍然發現 PyPy3 不穩定,在測試中仍然會出現一些奇怪的結果。一些其他的軟件包遇到了問題,比如 PyTest,因此它們放棄了對 PyPy3 的支持。
結論
Python 3.7 是速度最快的“官方”Python 版本,在我測試過的解釋器中,PyPy 則是最快的。
如果 Python2 以后用得越來越少,即使 PyPy3 無法比 PyPy 更快,我也希望它在速度上有所提升。