Python kodearen 4 milioi lerro mota egiaztatzeko bidea. 2. zatia

Gaur Dropbox-ek Python-eko hainbat milioi lerro lerrotarako mota-kontrola nola antolatu duen materialaren itzulpenaren bigarren zatia argitaratzen ari gara.

Python kodearen 4 milioi lerro mota egiaztatzeko bidea. 2. zatia

β†’ Irakurri lehen zatia

Laguntza mota ofiziala (PEP 484)

2014ko Hack Astean egin genuen mypy-rekin gure lehen esperimentu serioak Dropbox-en. Hack Astea Dropbox-ek antolatutako astebeteko ekitaldia da. Denbora horretan, langileek nahi dutena lan egin dezakete! Dropbox-en teknologia-proiektu ospetsuenetako batzuk horrelako ekitaldietan hasi ziren. Esperimentu honen ondorioz, mypy-k itxura ona duela ondorioztatu dugu, nahiz eta proiektua oraindik erabiltzeko prest ez dagoen.

Garai hartan, Python motako iradokizun sistemak estandarizatzeko ideia airean zegoen. Esan bezala, Python 3.0-tik aurrera posible zen funtzioetarako motako oharrak erabiltzea, baina hauek adierazpen arbitrarioak besterik ez ziren, sintaxi eta semantika definitu gabe. Programaren exekuzioan, oharpen hauek, gehienetan, besterik gabe, baztertu egin ziren. Hack Week-en ostean, semantika estandarizatzen hasi ginen lanean. Lan honek agerpena ekarri zuen 484 PEP (Guido van Rossum, Łukasz Langa eta biok elkarlanean aritu gara dokumentu honetan).

Gure motiboak bi aldetatik ikus zitezkeen. Lehenik eta behin, espero genuen Python-eko ekosistema osoak mota-iradokizunak erabiltzeko ikuspegi komun bat hartzea (Python-en "mota oharpenen" baliokide gisa erabiltzen den terminoa). Hori, arrisku posibleak kontuan hartuta, elkarren artean bateraezinak diren planteamendu asko erabiltzea baino hobea izango litzateke. Bigarrenik, modu irekian eztabaidatu nahi izan dugu motako oharpen mekanismoak Python komunitateko kide askorekin. Nahi hori, neurri batean, Python programatzaileen masa zabalaren aurrean hizkuntzaren oinarrizko ideietatik "apostatoen" itxura izan nahi ez genuelako agindu zuen. Dinamikoki idatzitako hizkuntza bat da, "ahate idazketa" izenez ezagutzen dena. Komunitatean, hasiera-hasieran, idazketa estatikoaren ideiaren aurrean jarrera susmagarri samarra ezin izan zen sortu. Baina sentimendu hori azkenean apaldu egin zen idazketa estatikoa ez zela derrigorrezkoa izango (eta jendea benetan erabilgarria zela konturatu ondoren).

Azkenean onartu zen hint motako sintaxia garai hartan mypy-k onartzen zuenaren oso antzekoa zen. PEP 484 Python 3.5-ekin kaleratu zen 2015ean. Python jada ez zen dinamikoki idatzitako hizkuntza bat. Gertaera hau Python historian mugarri esanguratsu bat dela pentsatzea gustatzen zait.

Migrazioaren hasiera

2015. urtearen amaieran, Dropbox-ek hiru laguneko taldea sortu zuen mypy-n lan egiteko. Guido van Rossum, Greg Price eta David Fisher zeuden. Une horretatik aurrera, egoera oso azkar hasi zen garatzen. Mypyren hazkuntzarako lehen oztopoa errendimendua izan zen. Goian adierazi dudan bezala, proiektuaren hasierako egunetan mypy inplementazioa C-ra itzultzea pentsatu nuen, baina ideia hau zerrendatik kanpo geratu da oraingoz. Sistema CPython interpretea erabiliz exekutatzen geratu ginen, hau ez da nahikoa azkarra mypy bezalako tresnetarako. (PyPy proiektuak, JIT konpiladore batekin Python inplementazio alternatibo batek ere ez digu lagundu.)

Zorionez, hobekuntza algoritmiko batzuk gure laguntza etorri dira hemen. Lehen "azeleragailu" indartsua egiaztapen inkrementala ezartzea izan zen. Hobekuntza honen atzean dagoen ideia sinplea zen: mypy-ren aurreko exekuziotik hona moduluaren menpekotasun guztiak aldatu ez badira, aurreko exekuzioan cachean gordetako datuak erabil ditzakegu mendekotasunekin lan egiten dugun bitartean. Aldatutako fitxategietan eta haien menpe zeuden fitxategietan soilik mota egiaztatzea egin behar genuen. Mypy are gehiago joan zen: modulu baten kanpoko interfazea aldatzen ez bazen, mypy-k suposatu zuen modulu hau inportatzen zuten beste modulu batzuk ez zirela berriro egiaztatu behar.

Gehienezko egiaztapenak asko lagundu digu lehendik dagoen kode kopuru handiak anotatzen. Kontua da prozesu honek mypy-ren exekuzio iteratibo asko inplikatzen dituela normalean, oharrak pixkanaka kodean gehitzen eta pixkanaka hobetzen diren heinean. Mypy-ren lehen exekuzioa oso motela izan zen oraindik, egiaztatzeko mendekotasun asko zituelako. Ondoren, egoera hobetzeko, urruneko cache-mekanismo bat ezarri dugu. Mypy-k detektatzen badu tokiko cachea litekeena dela zaharkituta egotea, kode-base osoaren uneko cachearen argazkia deskargatzen du biltegi zentralizatutik. Ondoren, kontrol inkremental bat egiten du argazki hau erabiliz. Honek urrats handi bat gehiago eman digu mypy-ren errendimendua handitzeko.

Dropbox-en mota egiaztatzea azkar eta naturaltasunez hartzeko garaia izan zen. 2016. urtearen amaieran, dagoeneko 420000 lerro inguru genituen Python kodea motako oharpenekin. Erabiltzaile asko gogotsu zeuden mota egiaztatzearekin. Gero eta garapen talde gehiagok erabiltzen zuten Dropbox mypy.

Orduan dena ondo zegoen, baina oraindik asko genuen egiteko. Aldizkako erabiltzaileen barne inkestak egiten hasi ginen, proiektuaren arazo-esparruak identifikatzeko eta lehenbailehen zein arazo konpondu behar diren ulertzeko (praktika hori oraindik ere erabiltzen da enpresan). Garrantzitsuenak, argi geratu zenez, bi zeregin ziren. Lehenik eta behin, kodearen estaldura mota gehiago behar genuen, bigarrenik, mypy behar genuen azkarrago lan egiteko. Erabat argi zegoen mypy bizkortzeko eta enpresa-proiektuetan ezartzeko gure lana oraindik oso urrun zegoela. Gu, bi zeregin hauen garrantziaz guztiz jabetuta, horiek konpontzeari ekin genion.

Produktibitate gehiago!

Kontrol gehigarriek mypy azkarrago egin zuten, baina tresna oraindik ez zen nahikoa azkarra. Kontrol gehigarri askok minutu bat inguru iraun zuten. Horren arrazoia inportazio ziklikoak izan ziren. Horrek ez du harrituko Python-en idatzitako kode-oinarri handiekin lan egin duen inor. Ehunka modulu multzoak genituen, eta bakoitzak zeharka beste guztiak inportatzen zituen. Inportazio-begizta bateko fitxategiren bat aldatzen bazen, mypy-k begizta horretako fitxategi guztiak prozesatu behar zituen, eta askotan begizta horretatik moduluak inportatzen zituen edozein modulu. Horrelako ziklo bat Dropbox-en arazo asko eragin zituen "mendekotasun-nahasketa" gaiztoa izan zen. Behin egitura honek ehunka modulu zituen, zuzenean edo zeharka proba asko inportatzen ziren bitartean, ekoizpen kodean ere erabiltzen zen.

Menpekotasun zirkularrak β€œasaltzeko” aukera aztertu genuen, baina ez genuen horretarako baliabiderik. Ezagutzen ez genuen kode gehiegi zegoen. Ondorioz, planteamendu alternatibo bat asmatu genuen. Mypy azkar funtzionatzea erabaki genuen, nahiz eta "mendekotasun korapilatsuak" egon. Helburu hori mypy daemon erabiliz lortu dugu. Daemon bat zerbitzari-prozesu bat da, bi gaitasun interesgarri inplementatzen dituena. Lehenik eta behin, kode-base osoari buruzko informazioa gordetzen du memorian. Horrek esan nahi du mypy exekutatzen duzun bakoitzean ez duzula inportatutako milaka mendekotasunekin erlazionatutako cacheko datuak kargatu beharrik. Bigarrenik, arreta handiz, egitura-unitate txikien mailan, funtzioen eta beste entitate batzuen arteko mendekotasunak aztertzen ditu. Adibidez, funtzioa bada foo funtzio bati deitzen dio bar, orduan menpekotasuna dago foo tik bar. Fitxategi bat aldatzen denean, deabruak lehenik, modu isolatuan, aldatutako fitxategia soilik prozesatzen du. Ondoren, fitxategi horretan kanpotik ikusten diren aldaketak aztertzen ditu, hala nola aldatutako funtzioen sinadurak. Daemonak inportazioei buruzko informazio zehatza erabiltzen du aldatutako funtzioa benetan erabiltzen duten funtzioak birritan egiaztatzeko soilik. Normalean, ikuspegi honekin, oso funtzio gutxi egiaztatu behar dituzu.

Hori guztia ezartzea ez zen erraza izan, jatorrizko mypy inplementazioa fitxategi bat aldi berean prozesatzera bideratu baitzen. Mugako egoera askori aurre egin behar izan genion, eta horien agerpenak behin eta berriz egiaztatzeak eskatzen zituen kodean zerbait aldatzen zen kasuetan. Adibidez, hau gertatzen da klase bati oinarrizko klase berri bat esleitzen zaionean. Nahi genuena egin ondoren, kontrol gehigarri gehienen exekuzio-denbora segundo gutxira murriztu ahal izan genuen. Garaipen handia iruditu zitzaigun.

Are produktibitate handiagoa!

Goian aipatu dudan urruneko cachearekin batera, mypy deabruak ia erabat konpondu zituen programatzaile batek mota egiaztatzea maiz exekutatzen duenean sortzen diren arazoak, fitxategi kopuru txiki batean aldaketak eginez. Hala eta guztiz ere, sistemaren errendimendua oso onuragarria den erabilera-kasuan oraindik oso urrun zegoen. Mypy-ren abiarazte garbi batek 15 minutu baino gehiago behar izan ditzake. Eta hau pozik egongo ginatekeena baino askoz gehiago izan zen. Astero egoera okerragoa zen, programatzaileek kode berria idazten eta lehendik zegoen kodeari oharrak gehitzen jarraitu zuten heinean. Gure erabiltzaileek errendimendu gehiagoren gosez jarraitzen zuten, baina pozik egon ginen erdibidean ezagututa.

Mypy-ri buruzko aurreko ideietako batera itzultzea erabaki genuen. Hots, Python kodea C kodea bihurtzeko. Cython-ekin (Python-en idatzitako kodea C kodera itzultzeko aukera ematen duen sistema) esperimentatzeak ez zigun bizkortze ikusgarririk eman, beraz, gure konpiladore propioa idazteko ideia berpiztea erabaki genuen. Mypy kode-baseak (Python-en idatzia) lehendik beharrezko motako oharpen guztiak zituenez, komenigarria izango zela pentsatu genuen oharpen hauek erabiltzen saiatzea sistema bizkortzeko. Ideia hau probatzeko prototipo bat azkar sortu nuen. Hainbat mikro-erreferentziatan errendimendua 10 aldiz baino gehiago igo dela erakutsi du. Gure ideia izan zen Python moduluak C moduluetara konpilatzea Cython erabiliz, eta motako oharpenak exekuzio-denboran mota egiaztatzen bihurtzea (normalean, motako oharpenak exekuzio-garaian ez ikusi egiten dira eta mota egiaztatzeko sistemek soilik erabiltzen dituzte). Egia esan, mypy inplementazioa Python-etik estatikoki idazteko diseinatuta zegoen hizkuntza batera itzultzea aurreikusi genuen, Python-en itxura (eta, gehienetan, funtzionatuko zuen). (Hizkuntza arteko migrazio mota hau mypy proiektuaren tradizio bat bihurtu da. Jatorrizko mypy inplementazioa Alore-n idatzi zen, gero Java eta Python-en hibrido sintaktiko bat zegoen).

CPython luzapen APIan zentratzea funtsezkoa izan zen proiektuak kudeatzeko gaitasunak ez galtzeko. Ez genuen makina birtual bat edo mypy-k behar zuen liburutegirik inplementatu beharrik izan. Horrez gain, oraindik ere Python ekosistema osoa eta tresna guztiak (pytest adibidez) sarbidea izango genuke. Honek esan nahi du garapenean interpretatutako Python kodea erabiltzen jarraitu genezakeela, eta horri esker, kode aldaketak egiteko eta probatzeko eredu oso azkar batekin lanean jarraitzeko, kodea konpilatu arte itxaron beharrean. Bi aulkitan eserita lan bikaina egiten ari ginela ematen zuen, nolabait esateko, eta gustatu zitzaigun.

Mypyc deitu genuen konpilatzailea (mypy frontend gisa erabiltzen baitu motak aztertzeko), oso proiektu arrakastatsua izan zen. Orokorrean, gutxi gorabehera 4 aldiz bizkortzea lortu dugu mypy maiz exekutatzeko cachean gorde gabe. Mypyc proiektuaren muina garatzeko Michael Sullivan, Ivan Levkivsky, Hugh Hahn eta ni neuk osatutako talde txiki batek 4 hilabete inguru behar izan ditu. Lan kopuru hori mypy berridazteko beharko zena baino askoz txikiagoa zen, adibidez, C++ edo Go-n. Eta proiektuan beste hizkuntza batean berridaztean egin beharko genituzkeenak baino askoz aldaketa gutxiago egin behar izan genituen. Gainera, espero genuen mypyc-a halako maila batera eraman genezakeela, beste Dropbox-eko programatzaile batzuek euren kodea konpilatzeko eta bizkortzeko erabil zezaketen.

Errendimendu maila hori lortzeko, ingeniaritza soluzio interesgarri batzuk aplikatu behar izan ditugu. Horrela, konpilatzaileak eragiketa asko bizkor ditzake maila baxuko C eraikuntza azkarrak erabiliz. Adibidez, konpilatutako funtzio-dei bat C funtzio-dei batera itzultzen da. Eta dei hori interpretatutako funtzio bati deitzea baino askoz azkarragoa da. Eragiketa batzuek, esate baterako, hiztegien bilaketak, oraindik ere CPython-en C-API dei arruntak erabiltzen zituzten, konpilatzean apur bat azkarragoak zirenak. Interpretazioak sortutako sistemaren karga gehigarria ezabatu ahal izan dugu, baina kasu honetan errendimendu aldetik irabazi txiki bat besterik ez da eman.

Eragiketa β€œmotel” ohikoenak identifikatzeko, kodearen profila egin dugu. Datu hauekin armatuta, mypyc-a doitzen saiatu ginen, eragiketa horietarako C kodea azkarragoa sortu zedin, edo dagokion Python kodea berridazten eragiketa azkarragoak erabiliz (eta batzuetan ez genuen nahikoa irtenbide sinplerik izan arazo hori edo beste arazo baterako) . Python kodea berridaztea arazoari irtenbide errazagoa izan ohi zen, konpilatzaileak automatikoki eraldaketa bera egitea baino. Epe luzera, eraldaketa horietako asko automatizatu nahi genituen, baina garai hartan mypy bizkortzera bideratu ginen ahalegin minimoarekin. Eta helburu horretara joatean, hainbat korner moztu ditugu.

Jarraitu ahal izateko ...

Irakurle maitea! Zeintzuk izan ziren mypy proiektuaz zuen inpresioak bere existentzia ezagutu zenuenean?

Python kodearen 4 milioi lerro mota egiaztatzeko bidea. 2. zatia
Python kodearen 4 milioi lerro mota egiaztatzeko bidea. 2. zatia

Iturria: www.habr.com

Gehitu iruzkin berria