這篇文章給大家分享的是有關(guān)java比python快的原因的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考。一起跟隨小編過來看看吧。
成都創(chuàng)新互聯(lián)公司-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價比新田網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式新田網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋新田地區(qū)。費用合理售后完善,十多年實體公司更值得信賴。Python慢,這幾種是常見的原因:“因為它是GIL(全局解釋器鎖)”,“因為它是解釋語言不是編譯語言”,“因為它是動態(tài)類型語言”。
推薦課程:Java教程。
究竟哪個原因?qū)π阅艿挠绊懘螅?/p>
“因為它是GIL”
現(xiàn)代計算機的 CPU 有多個核心,有時甚至有多個處理器。為了利用所有計算能力,操作系統(tǒng)定義了一個底層結(jié)構(gòu),叫做線程,而一個進(jìn)程(例如 Chrome瀏覽器)能夠生成多個線程,通過線程來執(zhí)行系統(tǒng)指令。這樣如果一個進(jìn)程是要使用很多 CPU,那么計算負(fù)載就會由多個核心分擔(dān),最終使得絕大多數(shù)應(yīng)用能更快地完成任務(wù)。
在撰寫本文時,我的 Chrome 瀏覽器開了 44 個線程。另外,基于 POSIX 的操作系統(tǒng)(如 Mac OS 和 Linux)的線程結(jié)構(gòu)和 API 與 Windows 操作系統(tǒng)是不一樣的。操作系統(tǒng)還負(fù)責(zé)線程的調(diào)度。
如果你沒寫過多線程程序,那么你應(yīng)該了解一下鎖的概念。與單線程進(jìn)程不同,在多線程編程中,你要確保改變內(nèi)存中的變量時,多個線程不會試圖同時修改或訪問同一個內(nèi)存地址。
CPython 在創(chuàng)建變量時會分配內(nèi)存,然后用一個計數(shù)器計算對該變量的引用的次數(shù)。這個概念叫做“引用計數(shù)”。如果引用的數(shù)目為 0,那就可以將這個變量從系統(tǒng)中釋放掉。這樣,創(chuàng)建“臨時”變量(如在 for 循環(huán)的上下文環(huán)境中)不會耗光應(yīng)用程序的內(nèi)存。
隨之而來的問題就是,如果變量在多個線程中共享,CPython 需要對引用計數(shù)器加鎖。有一個“全局解釋器鎖”會謹(jǐn)慎地控制線程的執(zhí)行。不管有多少個線程,解釋器一次只能執(zhí)行一個操作。
這對 Python 應(yīng)用的性能有什么影響?
如果應(yīng)用程序是單線程、單解釋器的,那么這不會對速度有任何影響。去掉 GIL 也不會影響代碼的性能。
但如果想用一個解釋器(一個 Python 進(jìn)程)通過線程實現(xiàn)并發(fā),而且線程是IO 密集型的(即有很多網(wǎng)絡(luò)輸入輸出或磁盤輸入輸出),那么就會出現(xiàn)下面這種 GIL 競爭:
如果 Web 應(yīng)用(如 Django)使用了 WSGI,那么發(fā)往 Web 應(yīng)用的每個請求都會由獨立的 Python 解釋器執(zhí)行,因此每個請求都只會有一個鎖。由于 Python 解釋器啟動很慢,一些 WSGI 實現(xiàn)就支持“守護(hù)模式”,保持 Python 進(jìn)程長期運行。
“因為它是解釋語言”
這條理由我也聽過很多,我發(fā)現(xiàn)它過于簡化了 CPython 的實際工作原理。當(dāng)你在終端上寫 python myscript.py 時,CPython 會啟動一長串操作,包括讀取、詞法分析、語法分析、編譯、解釋以及執(zhí)行。個過程的重點就是它會在編譯階段生成.pyc文件,字節(jié)碼會寫到__pycache__/下的文件中(如果是Python 3),或者寫到與源代碼同一個目錄中(Python 2)。不僅你編寫的腳本是這樣,所有你導(dǎo)入的代碼都是這樣,包括第三方模塊。
因此絕大多數(shù)情況下(除非你寫的代碼只會運行一次),Python是在解釋字節(jié)碼并在本地執(zhí)行。與Java和C#.NET比較一下:
Java將源代碼編譯成“中間語言”,然后Java虛擬機讀取字節(jié)碼并即時編譯成機器碼。.NET CIL也是一樣的,.NET的公共語言運行時(CLR)使用即時編譯將字節(jié)碼編譯成機器碼。
那么,既然它們都使用虛擬機,以及某種字節(jié)碼,為什么Python在性能測試中比Java和C#慢那么多?第一個原因是,.NET和Java是即時編譯的(JIT)。
即時編譯,即JIT(Just-in-time),需要一種中間語言,將代碼分割成小塊(或者稱幀)。而提前編譯(Ahead of Time,簡稱AOT)是編譯器把源代碼翻譯成CPU能理解的代碼之后再執(zhí)行。
JIT本身并不能讓執(zhí)行更快,因為它執(zhí)行的是同樣的字節(jié)碼序列。但是,JIT可以在運行時做出優(yōu)化。好的GIT優(yōu)化器能找到應(yīng)用程序中執(zhí)行最多的部分,稱為“熱點”。然后對那些字節(jié)碼進(jìn)行優(yōu)化,將它們替換成效率更高的代碼。
這就是說,如果你的應(yīng)用程序會反復(fù)做某件事情,那么速度就會快很多。此外,別忘了Java和C#都是強類型語言,所以優(yōu)化器可以對代碼做更多的假設(shè)。
“因為它是動態(tài)類型語言”
“靜態(tài)類型”語言要求必須在變量定義時指定其類型,例如C、C++、Java、C#和Go等。
而動態(tài)類型語言中盡管也有類型的概念,但變量的類型是動態(tài)的。
a = 1 a = "foo"
在這個例子中,Python用相同的名字和str類型定義了第二個變量,同時釋放了第一個a的實例占用的內(nèi)存。
靜態(tài)類型語言的設(shè)計目的并不是折磨人,這樣設(shè)計是因為CPU就是這樣工作的。如果任何操作最終都要轉(zhuǎn)化成簡單的二進(jìn)制操作,那就需要將對象和類型都轉(zhuǎn)換成低級數(shù)據(jù)結(jié)構(gòu)。
Python幫你做了這一切,只不過你從來沒有關(guān)心過,也不需要關(guān)心。
不需要定義類型并不是Python慢的原因。Python的設(shè)計可以讓你把一切都做成動態(tài)的。你可以在運行時替換對象的方法,可以在運行時給底層系統(tǒng)調(diào)用打補丁。幾乎一切都有可能。
而這種設(shè)計使得Python的優(yōu)化變得很困難。
那么,Python的動態(tài)類型是否讓Python更慢?
比較并轉(zhuǎn)換類型的代價很大。每次讀取、寫入或引用變臉時都會檢查類型
動態(tài)類型的語言很難優(yōu)化。許多替代Python的語言很快的原因就是它們犧牲了便利性來交換性能。
例如Cython(http://cython.org/),它通過結(jié)合C的靜態(tài)類型和Python的方式,使得代碼中的類型已知,從而優(yōu)化代碼,能夠獲得84倍的性能提升
總結(jié)
Python慢的主要原因是因為它的動態(tài)和多樣性。它能用于解決各種問題,但多數(shù)問題都有優(yōu)化得更好和更快的解決方案。
但Python應(yīng)用也有許多優(yōu)化措施,如使用異步、理解性能測試工具,以及使用多解釋器等。
對于啟動時間不重要,而代碼可能享受到JIT的好處的應(yīng)用,可以考慮使用PyPy。
對于代碼中性能很重要的部分,如果變量大多是靜態(tài)類型,可以考慮使用Cython。
感謝各位的閱讀!關(guān)于java比python快的原因就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!