掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢(xún)/運(yùn)營(yíng)咨詢(xún)/技術(shù)建議/互聯(lián)網(wǎng)交流
我是編譯型編程語(yǔ)言的忠實(shí)粉絲,一直都是。雖然解釋型編程語(yǔ)言可以讓開(kāi)發(fā)者更快地編寫(xiě)和測(cè)試代碼,但我仍然認(rèn)為編譯器是值得長(zhǎng)期投入的。

公司主營(yíng)業(yè)務(wù):成都做網(wǎng)站、網(wǎng)站制作、成都外貿(mào)網(wǎng)站建設(shè)、移動(dòng)網(wǎng)站開(kāi)發(fā)等業(yè)務(wù)。幫助企業(yè)客戶(hù)真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開(kāi)放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來(lái)的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶(hù)帶來(lái)驚喜。創(chuàng)新互聯(lián)推出青川免費(fèi)做網(wǎng)站回饋大家。
在我看來(lái),編譯型代碼有兩個(gè)明顯的優(yōu)勢(shì):
每次修改代碼都可以得到驗(yàn)證,甚至是在開(kāi)始運(yùn)行代碼之前。
更快的執(zhí)行速度。根據(jù)具體情況,代碼可能被編譯成非常底層的運(yùn)行指令。
我之所以要寫(xiě)這篇文章,是想比較一下編譯型代碼的執(zhí)行速度會(huì)比解釋型快多少。
因?yàn)槲移珢?ài)編譯型編程語(yǔ)言,所以現(xiàn)在有個(gè)問(wèn)題:我手頭有很多感興趣的代碼,但它們都是用 Python 寫(xiě)的,我該怎么辦?全部重寫(xiě)?部分重寫(xiě)?完全不重寫(xiě)?
在這篇文章里,我通過(guò)比較 Java、Go 和 Python 在處理不同任務(wù)時(shí)的性能表現(xiàn)來(lái)驗(yàn)證我對(duì)它們的一些先入之見(jiàn)。首先是 Python,我正在考慮要不要把它替換掉。至于 Java,我已經(jīng)是 20 多年的粉絲了,一路看著它成熟,不管是性能還是功能都在變得更好。最后是 Go,我兩年前才開(kāi)始用它,但真的很喜歡它。雖然 Go 相比 Java 還缺失了一些特性,比如類(lèi)繼承,但它的語(yǔ)法簡(jiǎn)潔而緊湊,編譯和執(zhí)行速度都很快,生成的代碼也很緊湊,還提供了優(yōu)雅的 goroutine 來(lái)實(shí)現(xiàn)并發(fā)處理。
以下是我的一些先入之見(jiàn)。
編譯型代碼的執(zhí)行速度比解釋型代碼要快一個(gè)數(shù)量級(jí)。之前,我比較了使用 JIT 和不使用 JIT 編譯 Java 代碼所獲得的性能,它們的比率大概是 30 比 1。
Go 的運(yùn)行速度比 Java 要快一點(diǎn)。我記得在之前的工作中做過(guò)一些測(cè)試,發(fā)現(xiàn) Go 在處理某些任務(wù)時(shí)要比 Java 快 30%,但最近一些文章又說(shuō) Java 比 Go 快。
我在之前的一篇文章中通過(guò)一些代碼比較過(guò) JIT 的性能,后來(lái)使用 Python 和 Go 也實(shí)現(xiàn)了一遍。這段代碼計(jì)算 100 的 Fibonacci 數(shù)值,每一輪計(jì)算 50 次,并打印執(zhí)行時(shí)間(納秒),共計(jì)算 200 輪。代碼可以在 https://github.com/rodrigoramirez/fibonacci 上找到。
三種語(yǔ)言的輸出結(jié)果看起來(lái)像這樣:
- Java Go Python
- ...
- 122 123 11683
- 119 107 11539
- 123 104 11358
- 120 115 11926
- 119 118 11973
- 120 104 11377
- 109 103 12960
- 127 122 15683
- 112 106 11482
- ...
平均值是這樣:
- Java Go Python
- 130 105 10050
可以看到,在計(jì)算 Fibonacci 數(shù)值時(shí),Java 比 Go 要慢一些,大概慢 24%,而 Python 幾乎慢了 100 倍,也就是 9458%。
這個(gè)結(jié)果驗(yàn)證了我最初對(duì) Java 和 Go 的判斷,但讓我感到吃驚的是 Python 的表現(xiàn),它慢得不只是一個(gè)數(shù)量級(jí),是兩個(gè)!
我在想 Python 為什么會(huì)花這么多時(shí)間。
我首先想到的是,很多人關(guān)注的是 Python 的易用性,并通過(guò)犧牲性能來(lái)快速獲得處理結(jié)果。我相信數(shù)據(jù)科學(xué)家們都是這么想的。況且有這么多現(xiàn)成的庫(kù)可以用,為什么要去找其他的?遲早會(huì)有人優(yōu)化它們的。
第二個(gè)原因是很多人沒(méi)有比較過(guò)不同的實(shí)現(xiàn),因?yàn)楹芏喑鮿?chuàng)公司在激烈的競(jìng)爭(zhēng)中忙于做出產(chǎn)品,根本無(wú)暇顧及什么優(yōu)化不優(yōu)化。
第三個(gè)原因,有一些方式可以讓同樣的 Python 代碼跑得更快。
在做了一些調(diào)研之后,我決定使用 PyPy 測(cè)試一下相同的 Python 代碼。PyPy 是 Python 的另一個(gè)實(shí)現(xiàn),它本身就是使用 Python 開(kāi)發(fā)的,包含了一個(gè)像 Java 那樣的 JIT 編譯器。跟 Java 一樣,我們需要忽略初始的輸出,并跳過(guò) JIT 編譯過(guò)程,得到的結(jié)果如下:
- Java Go Python PyPy
- 130 105 10050 1887
PyPy 的平均響應(yīng)速度比 Python 快 5 倍,但仍然比 Go 慢 20 倍。
以上的測(cè)試主要集中在數(shù)值的計(jì)算上,如果回到最開(kāi)始所說(shuō)的 Python 代碼,我還需要關(guān)注:
本文通過(guò)執(zhí)行簡(jiǎn)單的數(shù)學(xué)運(yùn)算得出這樣的結(jié)論:Go 的執(zhí)行速度比 Java 快一些,比解釋運(yùn)行的 Python 快 2 個(gè)數(shù)量級(jí)。
基于這樣的結(jié)果,我個(gè)人是不會(huì)使用 Go 來(lái)替換 Java 的。
另一方面,在高負(fù)載的關(guān)鍵任務(wù)上使用 Python 不是一個(gè)好的選擇。如果你正面臨這種情況,可以考慮使用 Python 編譯器作為短期的應(yīng)急方案。
在決定是否要重寫(xiě) Python 代碼時(shí),還需要考慮到其他因素,比如 IO 和 CPU 方面的問(wèn)題,但這些超出本文的范圍了。
有人提醒我,使用 Go 和 Java 的 64 位整型只能準(zhǔn)確計(jì)算出 92 的 Fibonacci 數(shù)值,再往后會(huì)出現(xiàn)溢出(譯者:所以代碼后來(lái)改成了計(jì)算 90 的 Fibonacci 數(shù)值)。但即使是這樣,本文的結(jié)論仍然是有效的。

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢(xún)/運(yùn)營(yíng)咨詢(xún)/技術(shù)建議/互聯(lián)網(wǎng)交流