本文驗(yàn)證Python 3.11的性能優(yōu)化。
Python 3.11 pre-release已經(jīng)發(fā)布。更新日志中提到:Python 3.11 is up to 10–60% faster than Python 3.10. On average, we measured a 1.25x speedup on the standard benchmark suite. See Faster CPython for details. — Python 3.11 Changelog.Python 在生產(chǎn)系統(tǒng)上的速度一直是被新手對比和吐槽。因?yàn)檎娴牟⒉豢欤瑸榱私鉀Q性能問題,我們總是需要使用 Cython 或 Tuplex 轉(zhuǎn)換關(guān)鍵代碼。Python 3.11中特意強(qiáng)了這個優(yōu)化,我們可以實(shí)際驗(yàn)證下到底有沒有官方說的平均1.25倍的提升呢?作為數(shù)據(jù)科學(xué)來說,我更期待的是看看它在 Pandas 處理DF方面是否有任何改進(jìn)。安裝Python 3.11 pre-release
windows的話可以在官方下載安裝文件,ubuntu可以用apt命令進(jìn)行安裝sudo apt install Python3.11
我們在工作中還不能直接使用3.11。所以需要創(chuàng)建單獨(dú)的虛擬環(huán)境來保存兩個 Python 版本。$ virtualenv env10 --python=3.10$ virtualenv env11 --python=3.11
# To activate v11 you can run,$ source env11/bin/activate
Python 3.11 與 Python 3.10 相比有多快?
我創(chuàng)建了一個小函數(shù)來生成一些斐波那契數(shù)。def fib(n: int) -> int: return n if n < 2 else fib(n - 1) + fib(n - 2)
用 Timeit 運(yùn)行上面的斐波那契數(shù)生成器來確定執(zhí)行時間。以下命令將重復(fù)生成過程十次并顯示最佳執(zhí)行時間。# To generate the (n)th Fibonacci numberpython -m timeit -n 10 "from fib import fib;fib(n)"
以下是 Python 3.10 和 Python 3.11 上的結(jié)果Python 3.11 在每次運(yùn)行中都優(yōu)于 Python 3.10。執(zhí)行時間大約是 3.11 版本的一半。
我其實(shí)是想確認(rèn)它在 Pandas 任務(wù)上的表現(xiàn)。但不幸的是,到目前為止Numpy 和 Pandas 還沒有支持 Python 3.11 的版本。冒泡排序
由于無法對 Pandas 進(jìn)行基準(zhǔn)測試,因此我們試試一般常見的計(jì)算時的性能對比,測量對一百萬個數(shù)字進(jìn)行排序所花費(fèi)的時間。排序是日常使用的最多也是最常用的一個操作了,相信它的結(jié)果可以為我們提供一個很好的參考。import randomfrom timeit import timeitfrom typing import List
def bubble_sort(items: List[int]) -> List[int]: n = len(items)
for i in range(n - 1):
for j in range(0, n - i - 1):
if items[j] > items[j + 1]: items[j], items[j + 1] = items[j + 1], items[j]
numbers = [random.randint(1, 10000) for i in range(1000000)]
print(timeit(lambda:bubble_sort(numbers),number=5))
上面的代碼生成了一百萬個隨機(jī)數(shù)。timeit 函數(shù)被設(shè)置為僅測量冒泡排序函數(shù)執(zhí)行的持續(xù)時間。Python 3.11 只用了 21 秒來排序,而 3.10 對應(yīng)的用時 39 秒。
I/O 操作是否存在性能差異?
這兩個版本在磁盤上讀寫信息的速度有差異嗎。在pandas讀取df還有深度學(xué)習(xí)讀取數(shù)據(jù)時 I/O 性能至關(guān)重要。這里準(zhǔn)備了2個程序,第一個將一百萬個文件寫入磁盤。from timeit import timeit
statement = """for i in range(100000): with open(f"./data/a{i}.txt", "w") as f: f.write('a')"""
print(timeit(statement, number=10))
我們使用 timeit 函數(shù)來打印持續(xù)時間。可以多次重復(fù)該任務(wù)并通過設(shè)置 number 參數(shù)取平均值。第二個程序也使用 timeit 函數(shù)。但它只讀取一百萬個文件。from glob import globfrom timeit import timeit
file_paths = glob("./data/*.txt")
statement = f"""for path in {file_paths}: with open(path, "r") as f: f.read()"""
print(timeit(statement, number=10))
雖然看起來 Python 3.10 比 Python 3.11 有優(yōu)勢,但并不重要。因?yàn)槎啻芜\(yùn)行這個實(shí)驗(yàn)會得出不同的結(jié)論,但是能夠肯定的是I/O方面并沒有提升。
總結(jié)
Python 3.11 仍然是一個預(yù)發(fā)布版本。3但它似乎是 Python 歷史上一個了不起的版本。它比之前的版本快了 60%,這個判斷還是沒毛病的,我們上面的一些實(shí)驗(yàn)也證明了 Python 3.11 確實(shí)更快。譯者注:前幾天剛把以前項(xiàng)目升級到了3.6,新項(xiàng)目都使用3.9開發(fā)了,現(xiàn)在3.11又馬上要發(fā)布了,而且還說性能有大幅提升,龜叔你這是要鬧哪樣。