回覆列表
  • 1 # 皮皮魯的科技星球

    先說結論:Python是一門動態型別的解釋語言,且有全域性直譯器鎖,這三點的底層實現導致了Python比Java、C++慢。

    背景知識

    01001000 00000001 11000011

    計算機CPU只能接受上面這樣的01二進位制語言,0和1用來控制高低電位。這樣的0個程式碼被稱為機器碼。

    C、C++等編譯型語言依靠編譯器將原始碼轉化為機器碼後才能執行,Python、Java等解釋型語言使用直譯器將原始碼翻譯後在虛擬機器上執行。對於Python,由於直譯器的存在,其執行效率比C語言慢幾倍甚至幾十倍。

    上圖展示各個語言在不同任務上的速度。C語言經過幾十年的發展,最佳化已經達到了極致。以C語言為基準,大多數解釋語言,如Python、R會慢十倍甚至一百倍。Julia這個解釋語言是個“奇葩”,因為它採用了JIT編譯技術。

    解決Python執行效率低的問題,一種解決辦法是使用C/C++語言重寫Python函式,但是這要求程式設計師對C/C++語言熟悉,且除錯速度慢,不適合絕大多數Python程式設計師。另外一種非常方便快捷的解決辦法就是使用Just-In-Time(JIT)技術。

    Python是一種解釋語言

    Python是一門解釋語言,Python為我們提供了基於硬體和作業系統的一個虛擬機器,並使用直譯器將原始碼轉化為虛擬機器可執行的位元組碼。位元組碼在虛擬機器上執行,得到結果。

    我們使用python example.py來執行一份原始碼時,Python直譯器會在後臺啟動一個位元組碼編譯器(Bytecode Compiler),將原始碼轉換為位元組碼,這個過程被稱為編譯階段。位元組碼是一種只能執行在虛擬機器上的檔案,Python的位元組碼預設字尾為.pyc,Python生成.pyc後一般放在記憶體中繼續使用,並不是每次都將.pyc檔案儲存到磁碟上。有時候我們會看到自己Python程式碼資料夾裡有很多.pyc檔案與.py檔案同名,但也有很多時候看不到.pyc檔案。pyc位元組碼透過Python虛擬機器與硬體互動。虛擬機器的出現導致程式和硬體之間增加了中間層,執行效率大打折扣。相信使用過虛擬機器軟體的朋友深有體會,在原生的系統上安裝一個虛擬機器軟體,在虛擬機器上再執行一個其他系統,經常感覺速度下降,體驗變差,這與Python虛擬機器導致程式執行慢是一個原理。

    Just-In-Time(JIT)技術為解釋語言提供了一種最佳化,它能克服上述效率問題,極大提升程式碼執行速度,同時保留Python語言的易用性。使用JIT技術時,JIT編譯器將Python原始碼編譯成機器直接可以執行的機器語言,並可以直接在CPU等硬體上執行。這樣就跳過了原來的虛擬機器,執行速度幾乎與用C語言程式設計速度並無二致。

    Python是動態型別的

    原生Python速度慢的另一個重要原因是變數型別不確定,即動態型別。Python宣告一個變數的語法很簡單,如a = 1,但沒有指定a到底是一個整數和一個浮點小數,甚至還可以把a賦值為一個字串。C++和Java中,變數都是有型別的,比如在C++中,宣告一個整數。

    int a = 1;

    計算機在執行程式碼時,必須知道是什麼型別的,才能給這個變數分配合適的記憶體,呼叫相應的指令。Python直譯器要進行大量的型別推斷,推斷出一個變數是什麼型別,轉換成計算機可執行的機器碼,這個過程會非常耗時。這個推斷的過程發生在將.py檔案換換成

    .pyc

    位元組碼的編譯階段。

    與Python不同,C/C++等編譯型語言要提前把整個程式先編譯好,再執行可執行檔案。而且只需要編譯一次,後面再使用這個程式時就不需要編譯了。

    Python編譯和執行都慢

    一個程式的執行時間一般是編譯時間加執行時間。

    總時間 = 編譯時間 + 執行時間

    Python動態型別的特點導致編譯時間較長,基於直譯器的特點導致其執行時間較長,加起來導致總時間比C++和Java慢。

    因此,Python非常容易上手,極大方便了開發人員,相應地,給程式設計師節省下來的時間就丟給了Python直譯器,導致Python執行程式的非常慢。

    突破這個鎖並不難,可以使用Python提供的multiprocessing庫來使用多核。

    總結

    Python是一門動態型別的解釋語言,且有全域性直譯器鎖,這三點的底層實現導致了Python比Java、C++慢。

  • 中秋節和大豐收的關聯?
  • 如何看待球爹的種種言論,他會不會影響到球哥的發展,是不是在蓄意炒作?