「Python大魔王」- @沈崴 宣稱說Python是最快的語言:

沈崴 - PYTHON 為什麼是最快的語言(上)沈崴的視頻 · 790 播放


我是視頻的作者,首先感謝朋友們的關注,並且誕生了這個論題,讓我可以看到大家對我視頻中的觀點的反饋。對於大家的討論,在日常時間允許的條件下,我會盡量參與。下面就我目前已經看到的朋友們的評論,做一下展開。


一、如果說 Python 協程是個優勢,那其他語言難道就沒有協程嗎?[1]

對其他語言來說「協程」或許是近年來才流行起來的一種「新技術」,但是對 Python 來說,協程早在 1998 年就已經出現並且大規模使用至今 —— 雖然從表面上看,各種語言的協程實現都大同小異,比如 Goroutine 和 gevent.patch_all() 都可以直接把整個語言協程化,使用起來非常方便 —— 似乎「只要增加了協程這個新特性就可以在任意語言中直接使用了」,但實際上協程具有極深的技術棧。Python 在之前的 20 多年裡,在積累上的領先,讓 Python 和其他語言有了本質上的區別 —— 「可以大規模商用」和「玩具」的區別。下面我來簡單摘取幾個方面,來說明在這之前的 20 多年裡面,Python 可以在協程技術上比「後起之秀們」多做多少事情。

1、調度器

和其他語言不同,Python 在長時間的積累中形成了大量可用的協程調度器,包括「搶佔式」、「非搶佔式」、「全功能」、「高性能」等各種實現,以適用於各種應用場景的需求。我使用過的調度器就有 Stackless Python、Gevent、Curio 以及 Eurasia[2] 等 —— 在這裡,Eurasia 是我於 2007 年開源的協程伺服器框架,使用了我自己開發的輕量級協程調度器,在性能上具有相當大的優勢。而在我開源的另一種協程伺服器框架 Slowdown[3] 中,我則是使用了在功能特性上更為全面的 Gevent 作為調度器,更加適合用於搭建複雜應用。在不同的應用場景下能夠擁有如此之多的選擇,是 Python 在協程技術上,成熟性的體現。我開發的 Eurasia 發佈於 2007 年,並在接下來的時間裡一直在投入使用 —— 直到 6 年以後 Goroutine 才開始出現 —— 而此時,距離 Python 著名的大規模協程應用 EVE online 的推出,更已經經過 10 年。

2、專業性

協程在「棧切換」「調用上下文」上,和一般程序具有很大的差別,特別是和線程池、多進程配合使用時,情況會更加複雜。如果沒有技術積累,開發者往往不知道「代碼在何種情況下會出現意外情況」,在出現錯誤時也不知道該如何正確地去調試 —— 這讓協程技術雖然門檻很低,入門容易,但是在實際使用中,它會變成一個巨型的「天坑」—— 而 Python 長期在協程上的實踐,形成了大量的技術積累,和無數的專家用戶。這讓你在遇到困難時,更容易查閱到解決方案,並獲得更多的幫助 —— 而不是讓你在協程技術領域中拓荒、踩坑。

3、文件/資料庫

要在協程架構中真正實現高並發,就必須要把系統中的所有操作全部進行非同步化 —— 任何沒有非同步化的節點全部都會變成性能瓶頸 —— 這相當於是要把整個操作系統都進行非同步化改造,如果沒有像 Python 這樣,經過了漫長的積累,是無法做到的。其中「文件」和「資料庫」就是很難非同步化的一個例子 —— 像 Python 中著名的 Tornado 就是隻實現了網路部分的「協程非同步化」,卻對文件 IO 無能為力的一個典型案例。這樣就只能被迫使用「基於多線程的應用層框架」,以「傳統的多線程模式」來處理文件和資料庫的請求。因此 Tornado 在事實上,仍然只是一個傳統的,受限於「文件 IO 瓶頸」以及「線程數量」的伺服器框架,同時資料庫伺服器也會變成整個系統的瓶頸。其他像 Goroutine 協程,在遇到文件及資料庫時,也同樣會退化為線程池,這也是其他各種語言的常態 —— 其實在 Python 世界中,以我自己為例,在使用協程的十幾二十年的時間裡,早已完成「緩存式文件 IO」及「資料庫底層磁碟 IO」的「協程非同步化」改造。這意味著高級的 Python 協程系統,不僅可以同時響應「百萬級的網路 IO」,也能處理同等並發規模的「文件讀寫」和「SQL 請求」。這使得 Python 的協程可以貫穿整個系統,沒有任何一個節點成為瓶頸。


二、說 Python 的運行速度快是不是太扯了?

視頻中的觀點是「程序性能只和瓶頸有關」,「語言快不快只和它擁有多少繞過瓶頸的手段有關」。開發效率越高,語言可以實現的性能優化就會越多,程序也就越快 —— 表面上可以用其他語言來改寫 Python 程序來獲得更高的執行效率,但是可能會花上好幾倍的時間 —— 而在同樣這段時間裡 Python 已經可以寫出更快的實現了。

在 PyPy 出現以前,Python 主要的 JIT 還是 Psyco 的時候,開發者就已經需要在 Unix/Win32 等不同平臺下來維護 Psyco 的 32 位版本了,但隨著 64 位 CPU 的逐漸普及,要想同時維護多個 OS,以及 MIPS/ARM/x86 等 CPU 架構,並同時維護 32 位和 64 位 CPU 下的版本,這讓維護 Psyco 本身就變得非常喫力,在 JIT 演算法上進行突破就變得更加不可能了。於是 64 位 CPU 的推出,成了壓跨項目的最後一根稻草,Psyco 的開發者在一篇文章中最後提到[4],他發現只有依賴 Python 的開發效率才能讓 JIT 更進一步,尤其是在開發階段 Python 可以直接解釋執行的特點讓 JIT 的調試工作變得非常容易。所以 Pysco 的開發者停止了 Psyco 項目,並轉而開創了 PyPy 項目 —— 這說明當一個項目的「複雜性」和「工作量」到達一定級別時,Python 已經不是僅僅能夠「快過」C 語言這麼簡單了,事情會變成「如果不使用 Python,問題可能根本就沒有辦法解決」的程度。故而在視頻裏「JIT 開發」被當作典型案例來使用 —— 當然這肯定不是孤例。

在許多時候,我們可能只是把 Python 當作「能跑起來的偽代碼」用來進行「快速原型開發」,一旦原型驗證完成,程序員會有一個本能的衝動,就是把它修改成「正式」的 C 語言版本來「一勞永逸」、「以利千秋」。IBus 輸入法便是從一個 Python 項目逐漸 C++ 化,並讓性能得到提升的一個很好的例子,但是更多的 Python 項目卻並沒有像意料中那樣,最終走上 C 語言化的這條道路,而是依舊堅持使用 Python 語言來進行開發。所以在「從『Python 快速原型開發』到『C 語言最終正式版』」的這個演進劇本里一定是出現了某種變數 —— 當開發者準備替換 Python 時,他們發現:

  1. 如果使用其他語言來強行改寫 Python 程序,由於瓶頸可能並不在語言這個層面,可能根本就無法在性能上得到可觀的提升。
  2. 如果不使用 Python,開發和維護的成本可能會大幅升高到無法承受的程度,強行替換 Python 只會讓程序在「功能」和「性能」上全面落後於 Python 版本的升級速度。

這指向一點:只要存在大量的 Python 項目,在經過無數次升級後,仍然沒有被 C 語言化,那麼在這些項目中,Python 的執行性能肯定不會輸於其他語言。「這些項目其實『都』是 Python 程序運行速度快的例子」。

在後面我即將發布的該系列視頻的第二集「PYTHON 為什麼是最快的語言(時空篇)」中,我會提到,由於 Python 語言簡潔的特性,會讓程序看上去都非常簡單,這掩蓋了每個 Python 程序事實上的複雜度,並給人以一個錯覺,以為用其他語言「也」可以輕鬆地寫出具有同等複雜度的程序。而等到真正用其他語言來著手實施的時候,才發現要實現同等複雜度的程序,語言性能下降的幅度,最終會出乎所有人的意料。


三、Python 在執行效率上會不會被編譯型語言吊打?

一個例子是 Java 的 WEB 服務常常會給人以性能不行的印象,然而事實卻是,Java 是一種逐行執行性能很高的語言,Java 的 socket 伺服器其實也擁有相當不錯的性能。但是當把應用邏輯加進來以後,為了漂亮地解決各種業務邏輯,服務架構變得異常複雜和龐大,以至於曾經出現過著名的「厚膠合層怪物」:「J2EE」,並最終把 Java 服務的性能從高空拽下地板。這說明在應用領域,「逐行執行性能」並不是「最終真實性能」的決定性因素。只有抑制住讓架構無限膨脹的衝動,才能在性能上最終勝出。PHP 這種「最好的編程語言」就曾長期被人批評為「不夠面向對象」、「缺少企業級開發能力」—— 但無論如何,在客觀上,這使得 PHP 很難寫出癡腫的應用架構,這導致 PHP 編寫的 WEB 服務,最終無論是在「性能」上還是在「功能」上都相當出色。

感謝 Python 出色的開發效率,重新製造一個輪子變成了一件似乎沒有什麼成本的事情,所以在 Python 中誕生了無數的 WEB 框架,這是一個只有在 Python 世界才會出現的獨特現象 —— 其中就包括我開源的「Slowdown」(及前面提到的「Eurasia」 等)項目。這是一個從 socket 底層到應用層,都完全使用 Python 開發的伺服器框架。那麼問題來了,這裡使用 Python 來進行應用層開發是可以理解的,但是為什麼連 socket 底層都要使用 Python 來開發,這不會有性能問題嗎?雖然有點違反直覺,但我的答案是:「使用 Python 進行底層開發只會讓伺服器性能變得更好」。

首先,使用 C 語言來處理 socket 通信和 IO 調度,的確會讓伺服器的底層性能有所提升。但是我們無可避免地要將底層介面「封裝」給 Python 等其他語言的「應用層框架」使用,這就涉及到了「底層」到「應用層」的介面轉換,在轉換過程中,相當一部分「底層介面」的「靈活性」將無可避免地犧牲掉了。

  1. 為了彌補這部分靈活性的損失,「底層」和「應用層」需要被迫調整出更加複雜龐大的封裝架構,增加更多的介面,來應付一些涉及到「底層」的需求。
  2. 如果底層和應用層實現了徹底的封裝隔離,許多通過操作底層可以直接輕鬆處理掉的需求將無法實現,或者只能通過其他相對複雜的方法來「近似」實現。

如果你是某個應用框架的用戶,看到這裡或許會有一種似曾相識的感覺。因為曾經有個功能你發現框架並沒有提供,而要把這個功能加上,則需要操作框架底層的權利,但是由於底層已經被「封裝」得「很好」是無法接觸的 —— 這最終讓你動彈不得 —— 而當問題被提交給框架的維護者時,解決方法往往是「為每個新增的問題設計出更多的介面」、「重構出更好的架構」。這樣,框架的複雜度就會逐漸滑入失控,變得臃腫,最終讓性能大幅下降。

而使用 Python 來統一開發「應用層框架」和「伺服器底層」,則可以避免讓「底層」和「應用層」進行跨語言介面轉換與封裝 —— 進一步,可以讓「底層直接穿透到頂層」,並最終讓「底層和應用層完全合併」,膠合層消失,框架(framework)程序庫(library)化。最終實現架構簡化,和性能反超。

而這,對 Slowdown 之類的協程伺服器具有著更加非凡的意義。由於協程是用之不竭的,所以可以「利用協程來維護『無數』長連接的上下文」來「等待長時間執行結果」而無需受到「傳統架構下線程數量的限制」,不需要通過「中斷連接上下文」來「釋放有限的線程」用額外的緩存架構和消息隊列來傳遞「長時間的執行結果」。這樣就可以把大量的因「受限於傳統線程架構」而增加的中間架構(中間伺服器、IPC)給精簡掉了。而此時,由於應用層中「長時間任務的上下文」和底層的「長連接上下文」是緊密耦合的,所以在這裡「底層穿透性」就尤為重要了。

結合上述內容,我們不難發現使用 Python 將底層與應用層進行融合,最終可以起到將整個系統的架構大幅簡化的驚人效果。這樣匪夷所思的結果出現了:使用 Python 進行伺服器底層開發,在整個系統層面反而取得了更好的性能。目前有大量的基於 Gevent 或者 asyncio 等框架的 Python 項目,仗著自己是協程架構,性能起點高,不管有意無意,通常會採用從網路底層到應用層的全棧式設計,雖然沒有用到編譯型語言來「優化」底層,卻在 benchmark 中都具有不錯的成績,這又成為 Python 「直接用於性能敏感的底層開發」,並「在性能上超過包括編譯型語言在內的其他語言」的典型案例。


四、和其他解釋性語言的性能比較

下面我們來談一下視頻中提到的「開發效率 == 運行效率」這一條,是否同樣可以套用在其他語言上的這個問題。簡單來說,答案是肯定的 —— 由於在「公平」「同等」的時間裡,開發效率高的編程語言一定可以實現更多的「優化」繞過更多的「瓶頸」,任何語言只要能夠擁有極致的開發效率,那麼(在不是強烈依賴於逐行性能的多數場景下)一定會擁有不錯的運行效率。這樣在許多時候,程序「運行效率」的比拼,其實就是「開發效率」的比拼。那麼其他語言是否擁有和 Python 一樣的開發效率呢?這就是一個非常依賴於主觀判斷的問題了。所以我試圖採用一個「更為客觀」的標準來對編程語言的開發效率進行評價:「有效項目數」—— 如果一種語言的開發效率很高,那麼在「足夠長的時間段」和「相同的時間」裏,它一定會開發出比別人更多的項目,「產量更高」。在翻閱了 Github 的「Ranking」、「Trending」、「Stars」中的項目之後,我發現這些指標幾乎都被兩大語言所「霸榜」:「Javascript」和「Python」。這意味著「單從客觀指標上來講」,大部分語言的開發效率尚不能達到 Python 的級別。依賴於開發效率,Python 在單位時間裡就可以生產出更多的優化演算法,繞過更多瓶頸,從而實現更高的執行效率。這樣 PYTHON 作為最快的編程語言,可以說實至名歸。

—— 2021年 1月 6日 17:27


五、「靠開發效率省下時間優化演算法」是否足以讓 Python 獲得比 C 更好的性能(況且很多業務代碼根本不存在多大優化空間),這點需要有說服力的實踐來舉例論證。

首先我們來思考一個業務問題,在登錄、驗證的場景中 Python 每秒能夠生成多少個圖形驗證碼?當驗證碼的並發請求數太多,超出程序處理能力的時候,我們應該如何去優化?

最簡單的想法,自然是使用 C 語言來優化出更快的 captcha 生成方法,如果性能還是不夠用,我們就增加伺服器,用來生成驗證碼 —— 不過在實際開發中,我們並不會真的這麼做 —— 今天我主要會用我「正在使用的」,並且開源的 Slowdown 伺服器作為說明案例。這個伺服器實現簡單、代碼不多,作為作者我又比較熟悉,拿來當例子會比較方便。

1、Captcha

Slowdown 的 captcha.py 模塊,會預生成一批隨時間輪替的驗證碼圖片,當請求驗證碼圖片時,它不會通過「即時演算」真的去生成一張圖片,而是會從「已有的圖片池」中,隨機抽取出一張圖片來返回給用戶。這樣每個用戶就可以拿到不同的圖片,而不同的用戶則可以對圖片進行復用。在這種情況下,圖片驗證碼的生成速度會快到令人窒息,從而讓性能測試變得毫無意義。

  • 儘管如此,我還是順手測了一下,生成 1000000(一百萬)個圖形驗證碼的時間大約是 1.9 秒 —— 這就回答了前面的第一個問題「Python 每秒能夠生成多少圖形驗證碼」(50萬+)。
  • 那麼這個「圖形驗證碼的優化實現」需要多少 Python 代碼?—— 76 行(含注釋)。

2、接下來是一個更大的案例

儘管性能並不是 Slowdown 最主要的設計目標(所以是我設計的伺服器裏性能最弱的一款,輕業務下,性能只有我其他 Python 伺服器作品的 1/2~1/3 ),但是這種完全使用 Python 開發的伺服器,在性能上與純 C 實現的伺服器並沒有特別嚴重的差距 —— 這裡我選擇的比較對象是 μwsgi,這是一款非常著名的,使用純 C 開發的非同步伺服器。具有和 nginx 相當的性能。

下面我們來做一下測試。因為都是已經公開發布的開源軟體,下面這些測試方案也比較簡單,有興趣的朋友可以自行搭建、測試。

# 用例: μwsgi
def application(env, start_response):
start_response(200 OK, [(Content-Type, text/html)])
# connection.execute(SQL)
return [CONTENT]

# 用例: slowdown
def handler(rw):
rw.start_response(200 OK, [(Content-Type, text/html)])
# connection.execute(SQL)
rw.write(CONTENT)
rw.close()

首先是空載測試,僅輸出「It works」頁面。

Server Software : uwsgi --http-socket :8080 --wsgi-file test.py &> /dev/null 2&>1
Document Length : 117 bytes
Concurrency Level : 1000
Requests per second: 22374.22 [#/sec] (mean)
Transfer rate : 3519.30 [Kbytes/sec] received

Server Software : slowdown {handler: mytest}
Document Length : 117 bytes
Concurrency Level : 1000
Requests per second: 7238.88 [#/sec] (mean)
Transfer rate : 1392.64 [Kbytes/sec] received

為了盡量貼近真實,我進一步設計了一個簡單的應用場景,完整的伺服器日誌輸出,並模擬一次耗時約 0.002 秒的資料庫操作(獨立資料庫伺服器)和 20KB 頁面。

Server Software : uwsgi --http-socket :8080 --wsgi-file test.py --logto access.log
Document Length : 20493 bytes
Concurrency Level : 1000
Requests per second: 418.94 [#/sec] (mean)
Transfer rate : 8406.01 [Kbytes/sec] received

Server Software : slowdown {handler: mytest, accesslog: access-%Y%m.log}
Document Length : 20493 bytes
Concurrency Level : 1000
Requests per second: 4546.93 [#/sec] (mean)
Transfer rate : 91302.86 [Kbytes/sec] received

可以發現,當沒有業務負載時,純 Python 開發的 Slowdown 伺服器,在性能上大約是純 C 伺服器的 1/3 。但是當少量業務被部署上去以後,C 伺服器的性能突然出現了大幅下降。最終 Python 伺服器的性能驚人地達到了 C 伺服器的 10 倍之多(高一個數量級)。這正是 Slowdown 的設計目標之一,放棄空載性能的爭奪,著重讓伺服器在具有實際業務負載的情況下,使性能緩慢下降,並在「滿業務負載」的情況下,最終穩定在一個很高的數值上。

3、開發效率和性能的關係

在上面這個例子中,類似 Captcha Token 這樣的聯合緩存、磁碟路徑及靜態文件緩存,這些幾十行代碼就能帶來極大性能提升的優化隨處可見。使用 Python 來開發伺服器還能夠省下大量的時間,用於全架構的體系性優化。還可以把瓶頸點用 C 語言進行逐點優化(正如視頻中所說,Python 和 C 並不是競爭關係,Python 就是 C)—— 這都是高開發效率下,擁有足夠的時間才能做到的結果。

Slowdown 僅僅是一個底層伺服器框架,用到的優化就已經如此之多了。那麼在更加複雜龐大的業務層,將會擁有多少的優化空間?—— 「理論上」C 語言也不是不能「從頭就開發出一樣的程序」,但是像 Python 這樣每隔幾十行就會有一個高效演算法,做到如此密集的優化,實際上是很難達到的。因為受制於開發效率,其他看似「逐行執行性能很高」的語言,最終也只能與 Python 爭一域之得失。業務越複雜,工作量越大,Python 在性能上的優勢就會越明顯。


六、GIL 會影響 Python 使用多核嗎?GIL 會影響 Python 的性能嗎?[5]

有句話叫做 Unix 程序員永遠可以把多核用完,Python 也不例外。操作系統本身,各式各樣的服務,被管道串起來的進程們,Apache、Nginx、MySQL、PostgreSQL、Redis、memcached、MQ …… 都可以把多核用完。不過,我們今天來談另外一個問題,為什麼 GIL 會影響到 Python 使用多核 —— 一般的看法是 GIL 的存在,讓 Python 同時只能允許一個線程執行,這樣 Python 就不能真正的使用多線程,自然也就不能透過多線程來用到多核了。

但是,為什麼要使用多線程?

—— 2021年 1月 8日 00:06

補充了注釋圖片。

—— 2021年 1月 10日 17:18


沈崴 - PYTHON 為什麼是最快的語言(上)沈崴的視頻 · 790 播放沈崴 - PYTHON 為什麼是最快的語言(中)沈崴的視頻 · 233 播放

參考

  1. ^本文分別就以下知乎網友提供的答案進行了進一步的展開:(一)潘俊勇(二)季晨曦、遊漢(三)山海師(四)季晨曦(五)SherlockGy(六)陸海綿
  2. ^Eurasia 基於協程非同步的伺服器及開發框架 https://code.google.com/archive/p/eurasia/
  3. ^Slowdown 基於協程非同步的伺服器及開發框架 https://github.com/wilhelmshen/slowdown
  4. ^由於時代過於久遠,該文章的歸檔暫時沒有找到。可以參閱 Psyco 項目主頁上「Related project」一節 http://psyco.sourceforge.net/links.html
  5. ^進一步內容可參考知乎「CPython有GIL是因為當年設計CPython的人偷懶嗎?」 https://www.zhihu.com/question/439920631/answer/1685766305


單就視頻來說,結論具有一定的誤導性。這裡的誤導性是指視頻中給出的結論需要更進一步指明前提條件,而這種前提條件受限於視頻的長短,面向人羣的知識儲備的因素,在追求通俗易懂的目標下給出的不是那麼地嚴謹容易對於知識儲備不足的人羣造成誤導,忽略了結論的前提條件而錯誤應用。

  1. 關於協程的問題

首先,為什麼要有協程?協程的產生是為瞭解決任務級並行問題下並行任務的指令流和數據上下文綁定,導致切換程序的指令流時不得不同時保存許多不必要的數據上下文,從而產生了性能瓶頸的問題。

任務級並行,簡單地說就是在相對固定的硬體設備上(如固定數目的CPU, 固定的內存,為了敘述的方便,這裡假設為單個單核CPU)通過不斷地切換在其上運行的任務(Task)從而達到並行的手段。所謂任務,包含了兩部分,一部分是任務本身要執行的指令,另一部分是執行這些指令所需要的上下文(此處借用了Mach微內核論文中的概念)。指令流的切換主要依靠中斷和操作系統調度,上下文的切換依賴虛擬內存和操作系統保存任務用到的各種寄存器。這個任務在經典的操作系統中通常被實現為我們所熟知的進程(Process),進程切換時需要同時切換指令流和上下文。可是在某些情況下,我們希望共享部分上下文,如共享虛擬內存空間。這樣,我們就得到了相對輕量的另一種任務級並行手段線程(Thread)。可是,即便是線程,依然需要保存大量的寄存器,同時由操作系統調度,這一過程不受用戶控制,因此未必能達到最佳性能。

協程(Coroutine)的出現將任務切換的上下文進一步地減少,在進行協程切換時,只需要保存更少的寄存器,從而節約了大量的內存,提高了切換的效率。另一方面,協程實現在用戶態,協程切換的調度過程可以由用戶控制。從操作系統內核的角度看來,它是發現不了協程的。操作系統內核看到的,只是一個普通的進程。為了方便理解,極為不嚴謹地說,協程的切換與普通函數調用是類似的。因為函數調用實際上需要保存一定的上下文(要返回的指令位置),然後跳轉到新的指令位置。協程比它的上下文稍微多一些,還可以調度,但是實現上是類似的。(要有更深的理解,可以參考Go語言實現中的PMG模型)

因為協程減少了無關的上下文切換,本身的調度可以受用戶控制。因此,在優良設計的前提下,協程能夠提供更強的任務級並行。這也是視頻中所說的,在別的才支持1k個的時候,協程可以支持100萬個的理由。

要注意,協程是一個概念,它本身可以用各種各樣的編程語言實現。那這一切和Python有何關係?猜測作者的意思,一是Python本身在協程方面起步早,有大量成熟的協程框架,設計優良。二是Python本身易於編寫,有助於程序員提高開發效率,有時候易於寫出優良的代碼。因此,Python藉助協程而快。

然而,這一說法存在誤導性。因為首先並不是所有的問題都可以通過任務級並行加速,這也是視頻作者說的IO密集型和計算密集型的區分。其次,也並非其他語言不可能有更好的協程框架。因此,Python並不是永遠都會因為協程獲得比其他語言更大的執行效率上的優勢,這一點是值得注意的。

2. 關於PyPy的問題

首先PyPy的原理是所謂的Meta Tracing。即為我們所熟知的靜態強類型編譯型語言(極為不嚴謹的說法,下同),如C, C++等,它們往往都是AOT(Ahead of Time) 預先靜態編譯的,因為源代碼本身提供的大量有幫助的類型信息,且變數的類型不會輕易地改變,因此可以在程序執行之前編譯成為機器碼提高執行效率。另一些動態弱類型解釋型語言,如Python, JavaScript等,由於源代碼本身缺乏類型信息,變數的類型可以動態的改變,編譯器不到運行時很難知道足夠的信息,無法編譯到機器碼,只能JIT(Just in Time)即時編譯,因為在運行時刻各類信息全了,對於反覆執行的熱點代碼,可以編譯為機器碼加速。對於一般的動態語言,其實在運行時刻的程序包含兩部分,一是被解釋執行的程序,二是解釋器。傳統的JIT一般只追蹤被解釋執行的程序的反覆執行的熱點部分,將它編譯為機器碼,其他部分交給解釋器解釋執行。PyPy所採用的Meta Tracing,即元追蹤,會追蹤解釋器本身,即多了一層追蹤,將解釋器反覆執行的熱點代碼進行JIT優化,這樣就可能產生更優的性能,這是PyPy擁有卓越性能的關鍵。具體可以參考Tracing the Meta-Level: PyPys Tracing JIT Compiler一文。PyPy相對來說無論概念上還是實現上是比較複雜的。

視頻中所說的PyPy是用Python本身實現的,這一說法也不夠嚴謹,PyPy是用RPython這一限制了Python的動態性後得到的Python子集實現的(當然也可以用Python實現,RPython是子集嘛,但這樣就慢了。因為限制了動態性,所以能夠更好地JIT,這也是PyPy性能卓越的關鍵。不過這恰恰說明不了Python的性能優勢,畢竟如果Python本身性能就足夠好,那為啥還要專門限制一下取子集呢

用PyPy來論證Python性能優勢,其實是有問題的。正因為Python本身的性能有問題,不夠快,才會有PyPy相對複雜的這套做法,最後做出一個比較快的實現,這其實反映了Python在性能上不那麼出眾。

綜上,這個視頻從Python宣傳的角度來講是不錯的,但是要說Python是最快的語言,那還是得加很多前提條件的。如果有可能,視頻的觀看者應該多學一些。如果有機會,視頻的作者可以多說一些。這樣會更好。


題目有相當的誤導性!

如果離開底層對C/C++擴展模塊功能的調用,Python還快嗎?,腳本編程語言字面上的運行速度往往只是編譯型C-程序的百分之一、甚至可能千分之一,Python也不例外!差別可能只是百分之一呢、還是千分之一?

長期以來,不少人對腳本編程語言有相當的誤解,尤其對腳本編程語言的運行速度很困擾。有的說很慢,有的說可以很快,究竟哪個對?事實上都對,也都不對!因為往往說的是在某個具體應用上,不能以偏概全。同一個腳本編程語言,可以讓它運行很快,也可以讓它運行很普通、很慢,這取決於腳本程序如何編寫、如何調用功能模塊,功能模塊如何獲得。。。等一系列不同情況。

腳本程序語言入門簡單、編程簡單,但是牽涉的問題可不簡單。

腳本程序語言的特色:

只有「敷雞之力」,卻能「借力使力」。

不是「一個好兵」,卻善「調兵遣將」。

不要自恃清高、老子天下第一!離開C/C++之類的編程語言,它什麼都不是!

不要小看這些腳本編程語言,即便個狐假虎威,還是大有一番作為!!


雖然我挺喜歡Python,但如果說Python運行速度快,那就太扯了,除非特指的是,在解釋型語言裏比較,但我也沒看過相關對比數據,所以也無法下結論。總之,Python一切都好,都速度確實是一大詬病,哪怕用Cython加速運行也一樣很慢。


完全是偷換概念,拿著一些在小白看來有點東西實際上是基本常識的幾個概念紙上談兵罷了。唬人都不夠

py的執行性能本來就比其他低很多,io不見得它能超越其他語言,更不見得可以領先到彌補執行性能的巨大弱勢,一個測試都不擺光靠說的還真的不信服。

還有靠開發效率來省下時間優化演算法,請問有任何有說服力的實踐表明比把py的演算法原型改成C在最終結果上時間更少性能更好嗎?更何況很多業務代碼根本不存在多大優化空間,請舉例論證

而且一個官方都承認的性能問題,有什麼必要去否認,py都又是tiobe年度了,什麼場景用什麼場景不用不是說明一切了麼


推薦閱讀:
相關文章