CPython 是 Python 的 C Implementation, C++20 有很多類 Python 的寫法,如果有 Python 的 C++ Based Implementation,是否可能比 CPython 更快?


C++ 20 長得再像 Python 也和用 C++ 20 去實現一個 Python 解釋器能有多少性能提升沒有半毛錢關係


我日常不寫 Python,但對腳本語言 Runtime 的性能做過些調研。這裡拋磚引玉下簡單的結論:關鍵根本不在於用什麼語言實現,而在於是否用上 JIT

我們不妨將題主提到的 CPython 作為基準,把它運行計算密集型任務的性能水平設為 1。那麼在此基礎上大概可以得到:

  • 1 這個量級,有經典的 Lua 和 Ruby 解釋器,以及最近的 QuickJS 和 Hermes JS 引擎。
  • 在約 20 到 50 這個量級,有 LuaJIT 和 V8 這種帶 JIT 的引擎。
  • 在約 200 以上的量級,有 Linux 和 Windows 這種操作系統(原生語言的 Runtime)。

我不太確定 WASM 和 Java 這種加了層 VM 的「原生」性能水平如何?粗略猜測在 100 左右,望不吝賜教。

然後讓我們看看,這幾個性能量級的 Runtime 是怎麼實現的:

  • 最慢、最簡單的解釋器是什麼語言寫的?既有 C 也有 C++
  • 一言不合快個幾十倍的 JIT 引擎是什麼語言寫的?既有 C 也有 C++
  • 最硬核的操作系統是什麼語言寫的?還是那句話……既有 C 也有 C++

所以,用 C 還是 C++ 寫 Implementation 重要嗎?不重要。比挑選編程語言更重要的,是基本的工程設計,以及實際場景下的取捨。你可能會有疑問,這性能都差了幾十倍,還有什麼取捨的必要嗎?這裡個人的理解是這樣的:

  • 最經典的解釋器,原理不外乎逐行解釋執行代碼。它自身速度雖慢,但非常輕便靈活。這種解釋器通常在幾萬行代碼內就可以實現,編譯到二進位的體積多在 1M 以下,非常容易嵌入到大型原生項目(如遊戲引擎)中,易於在低配硬體上運行,也非常容易與原生模塊互調。
  • JIT 雖然能比解釋器快幾十倍,但代碼量通常龐大且晦澀難懂,難以裁剪定製,資源佔用也比較高。QuickJS 只要一個神人就能做到基本完整支持 ES2019,而 V8 則要一支 Google 的精英團隊才維護得動。另外,JIT 機制需要一個 warm up 的過程,這也是不能忽視的性能開銷。

可以說,在是否使用 JIT 之間的取捨,也比用 C++ 還是 C 來實現 Runtime 更重要。讓我們看看工業界的實例:

  • Chrome 發布當年一騎絕塵地快,原因之一就在於 V8 這個工業級的 JIT 引擎,基本吊打當時 IE 的傳統 JS 解釋器。
  • Facebook 最近宣布在 RN 上取得的性能進步,反而在於它用不帶 JIT 的 Hermes,替代了安卓默認的 V8——嵌入式的 JS 引擎降低了 JS 與 Native 通信的成本,並可以編譯到自身的位元組碼,提高 App 的載入速度(這裡 Facebook 玩了個花招,宣稱 Hermes 支持了 AOT 編譯。但這種編譯到位元組碼的 AOT,運行時是肯定不如 V8 編譯到機器碼的 JIT 來得快的)。
  • V8 最近提供了一個 JIT-less 模式,可以關閉 JIT 來降低內存佔用。在 JIT-less 模式下面,運行計算密集型任務的效率慢了 10 倍以上,但真實世界裡 Web 應用場景的 Benchmark 水平則只慢了 40% 左右。

雖然腳本語言對 CPU 密集型的任務戰力不高,但打不過我可以叫大哥呀!在我熟悉的 Web 上,我個人看到了這樣的一種趨勢:嵌入式的腳本引擎和嵌入式的 WASM 原生代碼相輔相成,進一步增強了腳本世界和 Native 世界的聯繫。你可能發現我寫的是 JS 或 Python,但其中的每行代碼背後都是強力的原生代碼。腳本就像《攻殼機動隊》里那樣被「武裝」起來:

最後再次做個簡單的總結吧——對於腳本語言的在真實世界中的表現,最重要的不是你有沒有用上 C++20 的哪些新特性來實現 Python,而是 JIT 與基礎架構設計上的取捨。

參考:

  • https://bellard.org/quickjs/bench.html
  • https://engineering.fb.com/android/hermes/
  • https://v8.dev/blog/jitless


我猜測你提出這個問題的原因,是因為pypy?

你的想法大概是:

  1. pypy 是用 python 寫的 python 實現
  2. pypy 的性能 比 cpython 強
  3. 所以用 python 寫的 python 比用 C 寫的 python 強。
  4. c++20 像 python,所以寫出來就比 C 寫的 python 強?

啊,其實這個問題很多人以前就解釋過了,pypy 比 cpython 強的原因,與它用 python 寫的沒有半毛錢關係。準確的說,pypy 是一個高效的 python 解釋器,而它恰好是用 python 寫的,僅此而已。

這樣說吧,重寫 cpython,並且使用更先進更優秀的架構,引入JIT機制,確實有可能會比現在的 cpython 更強,但這與用什麼語言實現沒有關係。純粹是因為架構跟機制的原因。


不會,只要特性跟現在一樣,原理上你就算手工拿彙編重寫也很難提升了,你讓編譯器去干,編譯器也很難做的


首先你要知道 CPython 的性能瓶頸在什麼方面:動態類型+解釋型。

如果你用 C++ 重寫,雖然可以剔除掉 CPython 的一些缺點,例如採用更好的垃圾回收機制(不用引用計數),去除 GIL,加上 JIT,但是還是動態類型,基於虛擬機的解釋型語言,性能會有所提高,但不是特別多。並且副作用是目前的 C extension 都不能用了。

如果把 CPython 重寫成靜態類型 + 編譯型的語言,那就不叫 Python 了[1]。

[1] https://zh.wikipedia.org/wiki/Cython


推薦閱讀:
相关文章