眾所周知,Python 3.11 版本帶來了較大的性能提升,但是,它具體在哪些方面上得到了優化呢?除了著名的“香農計劃”外,它還包含哪些與性能相關的優化呢?本文將帶你一探究竟!
作者:Beshr KayaliPython 3.11 在幾天前發布了,它照例帶來了很多新特性,例如異常組、細粒度的錯誤位置與堆棧回溯、標準庫對 TOML 的解析支持,當然,還有備受大家期待的由 faster CPython 項目帶來的速度提升 。
譯者:豌豆花下貓@Python貓
英文:python-311-speedup-part-1" rel="external nofollow noreferrer">https://log.beshr.com/python-311-speedup-part-1
轉載請保留作者及譯者信息!
根據 pyperformance 的基準測試,CPython 3.11 比 CPython 3.10 平均快 25% 。這項改進的原因之一是 Guido 命名的“香農計劃”(即 faster CPython) 。對于 3.11 版本,這個計劃在兩個主要方向進行了大量優化:啟動時和運行時 。
除此之外,Python 3.11 還包含有其它的優化,這些優化不屬于香農計劃 。
在本文中,我將詳細介紹 3.11.0 穩定版中常規優化的細節(即非 faster CPython 項目的改進) 。
(譯注:作者表示將另寫一篇文章介紹 faster CPython 的改進細節,屆時,我也將繼續翻譯,敬請期待!)
目錄
- 優化了一些 printf 風格 % 的格式化代碼
- 優化了 Python 大整數的除法
- 優化了數字 PyLongs 求和
- 精簡列表的擴容操作,提升了 list.append 性能
- 減少了全 unicode 鍵的字典的內存占用
- 提升了使用asyncio.DatagramProtocol 傳輸大文件的速度
- 對于 math 庫:優化了 comb(n, k) 與 perm(n, k=None)
- 對于 statistics 庫:優化了 mean(data)、variance(data, xbar=None) 與 stdev(data, xbar=None)
- 純 ASCII 字符串的 unicodedata.normalize(),提升到常數時間
Python 3.10 中的一個簡單基準測試:
$ python -m pyperf timeit -s \'k = "foo"; v = "bar"' -- '"%s = %r" % (k, v)'.....................Mean +- std dev: 187 ns +- 8 ns但是使用 f-string 似乎要快 42%:$ python -m pyperf timeit -s \'k = "foo"; v = "bar"' -- 'f"{k!s} = {v!r}"'.....................Mean +- std dev: 131 ns +- 9 ns優化性能的手段是將簡單的 C 風格的格式化方法轉換為 f-string 方法 。在 3.11.0 中,只轉換了 %s、%r 和 %a 三種,但是目前有一個待合入的 python/cpython/pull/26160" rel="external nofollow noreferrer">pull request,將會支持:%d、%i、%u、%o、%x、%X、%f、 %e、%g、%F、%E、%G 。例如,下面是 Python 3.11 中相同基準測試的結果:
$ python -m pyperf timeit -s \'k = "foo"; v = "bar"' -- '"%s = %r" % (k, v)'.....................Mean +- std dev: 100 ns +- 5 ns大約快了 87%!當然,3.11 中其它的優化對此也有影響,比如更快的解釋器啟動時間 。優化了 Python 大整數的除法在 Python 3.10 中:
python -m pyperf timeit -s 'x=10**1000' -- 'x//10'.....................Mean +- std dev: 1.18 us +- 0.02 us在 Python 3.11 中:python -m pyperf timeit -s 'x=10**1000' -- 'x//10'.....................Mean +- std dev: 995 ns +- 15 ns大約快了18% 。這項優化源自 Mark Dickinson 的一個發現,即編譯器總會生成 128:64 的除法指令,盡管處理的是 30 位的數值 。
即使在 x64 上,Python 的除法也有些殘缺 。假設是 30 位數字,則多精度除法所需的基本結構是 64 位除以 32 位的無符號整數除法,產生一個 32 位的商(理想情況下還會產生一個 32 位余數) 。有一個 x86/x64 指令可以做到這一點,也就是 DIVL 。但是如果不使用內聯匯編,當前版本的 GCC 和 Clang 顯然做不到從 longobject.c 中發出該指令——它們只會在 x64 上使用 DIVQ(128 位除以 64 位的除法,盡管被除數的前 64 位被設為零),而在 x86 上則使用固有的 __udivti3 或 __udivti4 。經驗總結擴展閱讀
- 蛋糕粉可以做什么
- 微信好友刪除了怎么找回(微信注銷60天后警察還能查到嗎)
- 只知道微信昵稱刪除了對方怎么找對方(徹底刪除對方微信)
- 微信刪除好友怎么找回(微信已經實行雙向刪除了嗎)
- 哪些星座男女需要愛情保鮮?
- 五月初五什么節干什么 端午節除了吃粽子還有哪些風俗
- 端午節為何要吃咸鴨蛋 端午節除了吃粽子還有哪些風俗
- 金針菇放冰箱有點發黃
- 什么菜適合放蠔油
- 2023淘寶雙十二過后還有什么活動 除了雙十二過年網購還有活動嗎
