Python很慢?不一定哦
請注意,這有點(diǎn)夸張。
首先,我要說明我是專業(yè)從事python工作的,我做出了許多開源貢獻(xiàn),并且我所有的業(yè)余愛好項(xiàng)目都使用python進(jìn)行。我喜歡python。
但這很慢。
這是Reddit等論壇上的常見主題,人們說您不能使用python,因?yàn)樗\(yùn)行緩慢。是的,我們都知道python很慢。但是我們也知道,通常會(huì)使事情變慢的不是語言,而是算法。
是的,與C語言相比,python語言的運(yùn)行速度非常慢,但這并不是python速度慢的99%。 Python之所以緩慢,是因?yàn)樵S多(即使不是大多數(shù))Python程序員不在乎或不了解他們所做工作對(duì)性能的總體影響。編寫網(wǎng)絡(luò)應(yīng)用程序時(shí)基本上可以這樣做,但是如果編寫的庫可供成千上萬,十萬甚至一百萬的人使用,則可能會(huì)對(duì)性能產(chǎn)生重大影響。
讓我們看一些Python運(yùn)行緩慢的實(shí)際例子:
此處顯示的工具:
- pip是用于安裝python庫的工具
- virtualenv是用于創(chuàng)建封閉環(huán)境的工具,因此您無需全局安裝所有軟件包
- pytest是使用最廣泛的測試庫(也許標(biāo)準(zhǔn)庫中的unittest使用得更多,但至少非常接近)
我之所以選擇這些工具,是因?yàn)檫@是大多數(shù)人與python的首次互動(dòng),而這是我們專業(yè)人士每天與之互動(dòng)的東西。
- > time pip --version
- 0.34 seconds
- > time virtualenv -p (which python3) venv
- 6.24 seconds
- > time pytest # in an EMPTY directory
- 0.32 seconds
- > time pip install pytest # already installed!!!
- 0.85 seconds
這些測量是普遍的,因?yàn)樗鼈兪窃谛颅h(huán)境中且具有熱緩存(我對(duì)具有冷磁盤緩存的virtualenv進(jìn)行了15秒鐘的測量)。 如果您的虛擬環(huán)境具有很多依賴性,那么pip安裝(同樣不做任何事情)的時(shí)間會(huì)增加。 很多。 我在另一個(gè)項(xiàng)目中測量了2.1秒。
在這里算法才是問題,不是python。 我的意思是,當(dāng)我們解決算法問題時(shí),語言將成為問題,而且它永遠(yuǎn)不可能比更快的語言快,但是我們幾乎與任何地方都差不多。
我對(duì)此不夠強(qiáng)調(diào):python的基本工具鏈比它所需的要慢一個(gè)數(shù)量級(jí)。 有時(shí)更多。
Imports(導(dǎo)入)
在python中導(dǎo)入的慣用方式是個(gè)大問題。 在python中使用說說請求,您確實(shí)會(huì)在文件頂部導(dǎo)入請求,大多數(shù)人會(huì)認(rèn)為這是免費(fèi)的或接近免費(fèi)的。 在python中,它并不是完全免費(fèi)的,實(shí)際上,它要求導(dǎo)入urllib2,這是很慢的部分。 因此,人們認(rèn)為請求的導(dǎo)入是免費(fèi)的,而請求的作者則認(rèn)為urllib2的導(dǎo)入是免費(fèi)的。 到處都是這樣:成千上萬的人都認(rèn)為進(jìn)口是免費(fèi)的。 他們不是。
我最??吹降囊环N模式是:
- try:
- import numpy
- NUMPY_AVAILABLE = True
- except ImportError:
- NUMPY_AVAILABLE = False
并且在導(dǎo)入時(shí)運(yùn)行。我們什么時(shí)候在庫中使用該標(biāo)志?通常從不,并且numpy導(dǎo)入非常昂貴。我的機(jī)器上200ms。因此,對(duì)于您的應(yīng)用程序而言,它的啟動(dòng)性能非常出色,因?yàn)樗墓δ茉趩?dòng)路徑中沒有使用,在許多情況下根本沒有使用。
開發(fā)時(shí),這非常令人沮喪,因?yàn)槟骄梢栽谡麄€(gè)工作日平均每分鐘重新啟動(dòng)一次該過程。
我很高興看到一年以前,因此pytz停止在導(dǎo)入時(shí)解析其整個(gè)時(shí)區(qū)數(shù)據(jù)庫。從Django(可以說是最流行的Web框架)的啟動(dòng)開始,這節(jié)省了約100毫秒的時(shí)間?,F(xiàn)在考慮一下,這種微小的變化將在10年內(nèi)節(jié)省多少千瓦時(shí)。每次運(yùn)行測試時(shí),每次啟動(dòng)Web Worker時(shí),都會(huì)在每個(gè)使用Django的站點(diǎn)上進(jìn)行。這僅適用于Django!許多其他庫和程序都使用pytz。
千紙之死
另一個(gè)問題是,人們認(rèn)為“哦,啟動(dòng)時(shí)只有10毫秒,這沒什么大不了的”,但是如果該啟動(dòng)每天進(jìn)行數(shù)百萬次,那將是真實(shí)數(shù)字。對(duì)于進(jìn)口來說,這是正確的,但在更多事情上也是如此。后續(xù)問題是,人們已經(jīng)引入了100種此類減速后,就會(huì)認(rèn)為“僅再增加10毫秒”。因此,現(xiàn)在您只需要在1秒的基礎(chǔ)上再加上10毫秒,即1%。沒什么大不了的!因此,現(xiàn)在可以再增加10毫秒,這略低于1%。每次您使其變慢時(shí),它就會(huì)變得更便宜(以百分比為單位),以使其變得更慢。
請不要使用這種邏輯!
上面的pip安裝示例是一個(gè)很好的案例研究。從磁盤加載字典并檢查其是否包含字符串“ pytest”將比python的啟動(dòng)時(shí)間(約30毫秒)少。但這不是pip在做什么,它正在文件系統(tǒng)中運(yùn)行,甚至正在加載python文件以獲取其版本號(hào)(為什么?我沒有詢問它們!為什么它們?nèi)匀粵]有以有效的格式存儲(chǔ)?)。
在pytest中,我們有一個(gè)類似的問題,性能回歸已被引入了上千次,但是現(xiàn)在一切都很緩慢,并且沒有明顯的方法來擺脫這種情況。我已經(jīng)提供了一些補(bǔ)丁,但是由于我在進(jìn)行優(yōu)化時(shí)進(jìn)行了其他更改,因此我獲得的大部分收益都被抹去了!
最后,我放棄了提交補(bǔ)丁程序,并構(gòu)建了一個(gè)名為hammett的新測試運(yùn)行程序,該測試運(yùn)行程序與pytest兼容,但速度更快。我的意思是走得更快。我希望,如果有替代方案,人們可以看到存在另一個(gè)可能運(yùn)行緩慢的世界。
我們?nèi)绾问筽ython更快?
我們需要關(guān)心這一問題。
我們需要了解進(jìn)口不是免費(fèi)的。
我們需要研究整個(gè)生態(tài)系統(tǒng)的基本構(gòu)建模塊,或者解決基本程序和庫中的性能問題,或者替換它們。
我們需要衡量。
一些開始的地方:
- pytest:代替我使用hammett,或敦促pytest的向后兼容性大幅度中斷,以提高性能
- pip:至少緩存一些結(jié)果!我應(yīng)該能夠在執(zhí)行每個(gè)命令之前運(yùn)行“ pip install -r requirements.txt”,而不會(huì)注意到它
- virtualenv:我還沒有研究過,但是似乎可以寫1218個(gè)文件,總計(jì)11.6MB,可以加快速度,或者避免做一些工作
- 編寫基準(zhǔn):這可能是最簡單的。例如,您可以將工具與其他語言的同類工具進(jìn)行基準(zhǔn)測試。我們至少應(yīng)該知道我們是否比例如java慢一百倍。
更新:
事實(shí)證明,virtualenv家伙已經(jīng)在此之上了!現(xiàn)在,版本20需要0.8秒才能完成與之前花費(fèi)6.4相同的任務(wù)。為此,virtualenv團(tuán)隊(duì)值得高度贊揚(yáng)!
原文網(wǎng)址:https://kodare.net/2020/05/19/python-is-slow-does-not-have-to-be.html