首頁 > Java > java教程 > java為什麼比python快

java為什麼比python快

(*-*)浩
發布: 2019-05-24 14:11:45
原創
5063 人瀏覽過

Python慢​​,這幾種是常見的原因:“因為它是GIL(全局解釋器鎖)”,“因為它是解釋語言不是編譯語言”,“因為它是動態類型語言”。

推薦課程:Java教學

java為什麼比python快

究竟哪個原因對效能的影響最大?

「因為它是GIL」

現代電腦的 CPU 有多個核心,有時甚至有多個處理器。為了利用所有運算能力,作業系統定義了一個底層結構,叫做線程,而一個進程(例如 Chrome瀏覽器)能夠產生多個線程,透過線程來執行系統指令。這樣如果一個行程是要使用很多 CPU,那麼運算負載就會由多個核心分擔,最終使得絕大多數應用程式能更快完成任務。

在撰寫本文時,我的 Chrome 瀏覽器開了 44 個執行緒。另外,基於 POSIX 的作業系統(如 Mac OS 和 Linux)的執行緒結構和 API 與 Windows 作業系統是不一樣的。作業系統也負責線程的調度。

如果你沒寫過多線程程序,那麼你應該了解一下鎖的概念。與單執行緒進程不同,在多執行緒程式設計中,你要確保改變記憶體中的變數時,多個執行緒不會試圖同時修改或存取同一個記憶體位址。

CPython 在建立變數時會分配內存,然後用一個計數器計算對該變數的引用的次數。這個概念叫做「引用計數」。如果引用的數目為 0,那就可以將這個變數從系統中釋放掉。這樣,建立「臨時」變數(如在 for 迴圈的上下文環境中)不會耗光應用程式的記憶體。

隨之而來的問題是,如果變數在多個執行緒中共享,CPython 需要對引用計數器加鎖。有一個「全域解釋器鎖」會謹慎地控制執行緒的執行。不管有多少個線程,解釋器一次只能執行一個操作。

這對 Python 應用的效能有什麼影響?

如果應用程式是單執行緒、單解釋器的,那麼這不會對速度有任何影響。去掉 GIL 也不會影響程式碼的效能。

但如果想用一個解釋器(一個Python 進程)透過線程實現並發,而且線程是IO 密集型的(即有很多網路輸入輸出或磁碟輸入輸出),那麼就會出現下面這種GIL 競爭:

java為什麼比python快

如果Web 應用程式(如Django)使用了WSGI,那麼發送到Web 應用程式的每個請求都會由獨立的Python 解譯器執行,因此每個請求只會有一個鎖。由於 Python 解釋器啟動很慢,一些 WSGI 實作就支援“守護模式”,保持 Python 進程長期運行。

「因為它是解釋語言」

這個理由我也聽過很多,我發現它過於簡化了 CPython 的實際運作原理。當你在終端機上寫 python myscript.py 時,CPython 會啟動一長串操作,包括讀取、字法分析、語法分析、編譯、解釋以及執行。個過程的重點就是它會在編譯階段產生.pyc文件,字節碼會寫到__pycache__/下的文件(如果是Python 3),或寫到與原始碼同一個目錄(Python 2)。不僅你寫的腳本是這樣,所有你導入的程式碼都是這樣,包括第三方模組。

因此絕大多數情況下(除非你寫的程式碼只會運行一次),Python是在解釋字節碼並在本地執行。與Java和C#.NET比較一下:

Java將原始程式碼編譯成“中間語言”,然後Java虛擬機讀取字節碼並即時編譯成機器碼。 .NET CIL也是一樣的,.NET的公共語言執行時期(CLR)使用即時編譯將字節碼編譯成機器碼。

那麼,既然它們都使用虛擬機,以及某種字節碼,為什麼Python在效能測試中比Java和C#慢那麼多?第一個原因是,.NET和Java是即時編譯的(JIT)。

即時編譯,即JIT(Just-in-time),需要一種中間語言,將程式碼分割成小塊(或稱幀)。而提前編譯(Ahead of Time,簡稱AOT)是編譯器把原始碼翻譯成CPU能理解的程式碼之後再執行。

JIT本身並不能讓執行更快,因為它執行的是同樣的字節碼序列。但是,JIT可以在運行時做出最佳化。好的GIT優化器能找到應用程式中執行最多的部分,稱為「熱點」。然後對那些字節碼進行最佳化,將它們替換成效率更高的程式碼。

這就是說,如果你的應用程式會反覆做某件事情,那麼速度就會快很多。此外,別忘了Java和C#都是強型別語言,所以優化器可以對程式碼做更多的假設。

「因為它是動態型別語言」

#

「靜態類型」語言要求必須在變數定義時指定其類型,例如C、C 、Java、C#和Go等。

而動態型別語言中儘管也有型別的概念,但變數的型別是動態的。

a = 1
a = "foo"
登入後複製

在這個例子中,Python用相同的名字和str類型定義了第二個變量,同時釋放了第一個a的實例佔用的記憶體。

靜態型別語言的設計目的並不是折磨人,這樣設計是因為CPU就是這樣運作的。如果任何操作最終都要轉換成簡單的二進位操作,那就需要將物件和類型轉換成低階資料結構。

Python幫你做了這一切,只不過你從來沒有關心過,也不需要關心。

不需要定義類型並不是Python慢​​的原因。 Python的設計可以讓你把一切都做成動態的。你可以在運行時替換物件的方法,可以在運行時為底層系統呼叫打補丁。幾乎一切都有可能。

而這個設計使得Python的最佳化變得很困難。

那麼,Python的動態類型是否讓Python更慢?

比較並轉換類型的代價很大。每次讀取、寫入或引用變臉時都會檢查類型

動態類型的語言很難最佳化。許多替代Python的語言很快的原因就是它們犧牲了便利性來交換表現。

例如Cython(http://cython.org/),它透過結合C的靜態類型和Python的方式,使得程式碼中的類型已知,從而優化程式碼,能夠獲得84倍的性能提升

總結

Python慢​​的主要原因是因為它的動態和多樣性。它能用於解決各種問題,但多數問題都有優化得更好、更快的解決方案。

但Python應用也有許多最佳化措施,如使用非同步、理解效能測試工具,以及使用多重解釋器等。

對於啟動時間不重要,而程式碼可能享受到JIT的好處的應用,可以考慮使用PyPy。

對於程式碼中效能很重要的部分,如果變數大多是靜態類型,可以考慮使用Cython。

以上是java為什麼比python快的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板