Leiðin til að slá inn 4 milljón línur af Python kóða. 2. hluti

Í dag erum við að gefa út seinni hluta þýðingarinnar á efni um hvernig Dropbox skipulagði tegundarstýringu fyrir nokkrar milljónir línur af Python kóða.

Leiðin til að slá inn 4 milljón línur af Python kóða. 2. hluti

Lestu fyrsta hluta

Opinber gerð stuðningur (PEP 484)

Við gerðum fyrstu alvarlegu tilraunirnar okkar með mypy á Dropbox á Hack Week 2014. Hack Week er viku viðburður sem Dropbox hýsir. Á þessum tíma geta starfsmenn unnið við hvað sem þeir vilja! Sum af frægustu tækniverkefnum Dropbox hófust á viðburðum sem þessum. Sem afleiðing af þessari tilraun komumst við að þeirri niðurstöðu að mypy lítur efnilega út, þó verkefnið sé ekki enn tilbúið til almennrar notkunar.

Á þeim tíma var hugmyndin um að staðla Python gerð vísbendingakerfisins í loftinu. Eins og ég sagði, þar sem Python 3.0 var hægt að nota tegundaskýringar fyrir föll, en þetta voru bara handahófskennd tjáning, án skilgreindrar setningafræði og merkingarfræði. Við framkvæmd forritsins voru þessar athugasemdir að mestu leyti einfaldlega hunsaðar. Eftir Hack Week fórum við að vinna í að staðla merkingarfræði. Þessi vinna leiddi til uppkomu SLF 484 (Guido van Rossum, Łukasz Langa og ég unnum saman um þetta skjal).

Það væri hægt að skoða ástæður okkar frá tveimur hliðum. Í fyrsta lagi vonuðum við að allt Python vistkerfið gæti tileinkað sér sameiginlega nálgun við notkun tegundavísbendinga (hugtak sem notað er í Python sem jafngildi „tegundaskýringa“). Þetta, miðað við hugsanlega áhættu, væri betra en að nota margar aðferðir sem eru ósamrýmanlegar. Í öðru lagi vildum við ræða opinskátt um tegundaskýringarkerfi við marga meðlimi Python samfélagsins. Þessi löngun var að hluta til ráðist af þeirri staðreynd að við myndum ekki vilja líta út eins og „fráhvarfsmenn“ frá grunnhugmyndum tungumálsins í augum breiðs fjölda Python forritara. Það er kraftmikið vélritað tungumál, þekkt sem "önd vélritun". Í samfélaginu, strax í upphafi, gat ekki annað en komið upp dálítið grunsamlegt viðhorf til hugmyndarinnar um truflanir vélritun. En þessi tilfinning dvínaði á endanum eftir að ljóst var að kyrrstætt vélritun yrði ekki skylda (og eftir að fólk áttaði sig á því að það var í raun gagnlegt).

Tegundarvísbending setningafræði sem að lokum var tekin upp var mjög svipuð því sem mypy studdi á þeim tíma. PEP 484 kom út með Python 3.5 árið 2015. Python var ekki lengur kraftmikið vélritað tungumál. Mér finnst gaman að hugsa um þennan atburð sem merkan áfanga í sögu Python.

Upphaf fólksflutninga

Í lok árs 2015 stofnaði Dropbox teymi þriggja manna til að vinna að mypy. Meðal þeirra voru Guido van Rossum, Greg Price og David Fisher. Frá þeirri stundu fór ástandið að þróast mjög hratt. Fyrsta hindrunin fyrir vexti mypy var frammistaða. Eins og ég gaf í skyn hér að ofan, í árdaga verkefnisins hugsaði ég um að þýða mypy útfærsluna yfir á C, en þessi hugmynd var strikuð út af listanum í bili. Við vorum föst við að keyra kerfið með því að nota CPython túlkinn, sem er ekki nógu hratt fyrir verkfæri eins og mypy. (PyPy verkefnið, önnur Python útfærsla með JIT þýðanda, hjálpaði okkur ekki heldur.)

Sem betur fer hafa nokkrar reikniritumbætur komið okkur til hjálpar hér. Fyrsti öflugi „hraðalinn“ var innleiðing stigvaxandi eftirlits. Hugmyndin á bak við þessa endurbót var einföld: ef öll ósjálfstæði einingarinnar hafa ekki breyst frá fyrri keyrslu mypy, þá getum við notað gögnin sem eru í skyndiminni í fyrri keyrslu meðan unnið er með ósjálfstæði. Við þurftum aðeins að framkvæma tegundathugun á breyttu skránum og á þeim skrám sem voru háðar þeim. Mypy gekk meira að segja aðeins lengra: ef ytra viðmót einingar breyttist ekki, gerði mypy ráð fyrir að aðrar einingar sem fluttu inn þessa einingu þyrfti ekki að athuga aftur.

Stigvaxandi athugun hefur hjálpað okkur mikið við athugasemdir við mikið magn af núverandi kóða. Málið er að þetta ferli felur venjulega í sér margar endurteknar keyrslur af mypy þar sem athugasemdum er smám saman bætt við kóðann og smám saman bætt. Fyrsta keyrsla mypy var enn mjög hæg vegna þess að það hafði mikið af ósjálfstæði að athuga. Síðan, til að bæta ástandið, innleiddum við fjarstýrð skyndiminni. Ef mypy skynjar að líklegt er að staðbundið skyndiminni sé úrelt, hleður það niður núverandi skyndiminni skyndimynd fyrir allan kóðagrunninn úr miðlægu geymslunni. Það framkvæmir síðan stigvaxandi athugun með því að nota þessa skyndimynd. Þetta hefur tekið okkur enn eitt stórt skref í átt að því að auka afköst mypy.

Þetta var tímabil hröðrar og eðlilegrar upptöku á tegundaskoðun hjá Dropbox. Í lok árs 2016 vorum við þegar með um það bil 420000 línur af Python kóða með tegundaskýringum. Margir notendur voru áhugasamir um tegundaskoðun. Fleiri og fleiri þróunarteymi voru að nota Dropbox mypy.

Allt leit vel út þá en við áttum samt mikið eftir að gera. Við byrjuðum að gera reglulegar innri notendakannanir til að greina vandamál verkefnisins og skilja hvaða vandamál þarf að leysa fyrst (þessi venja er enn notuð í fyrirtækinu í dag). Mikilvægust, eins og ljóst var, voru tvö verkefni. Í fyrsta lagi þurftum við meiri tegundarumfjöllun á kóðanum, í öðru lagi þurftum við mypy til að vinna hraðar. Það var alveg ljóst að vinnu okkar við að hraða mypy og innleiða það í fyrirtækisverkefni var enn langt frá því að vera lokið. Við, fullkomlega meðvituð um mikilvægi þessara tveggja verkefna, fórum að leysa þau.

Meiri framleiðni!

Stigvaxandi athuganir gerðu mypy hraðari, en tólið var samt ekki nógu hratt. Margar stigvaxandi athuganir stóðu í um eina mínútu. Ástæðan fyrir þessu var sveiflukenndur innflutningur. Þetta kemur líklega engum á óvart sem hefur unnið með stóra kóðabasa skrifaða í Python. Við höfðum sett af hundruðum eininga, sem hver um sig flutti óbeint inn allar hinar. Ef einhverri skrá í innflutningslykkju var breytt þurfti mypy að vinna úr öllum skrám í þeirri lykkju, og oft hvaða einingar sem fluttu inn einingar úr þeirri lykkju. Ein slík hringrás var hinn alræmdi „ósjálfstæðisflækja“ sem olli miklum vandræðum hjá Dropbox. Þegar þessi uppbygging innihélt nokkur hundruð einingar, á meðan hún var flutt inn, beint eða óbeint, mörg próf, var hún einnig notuð í framleiðslukóða.

Við veltum fyrir okkur möguleikanum á að „aflækja“ hringlaga ósjálfstæði, en við höfðum ekki fjármagn til þess. Það var of mikið af kóða sem við þekktum ekki. Fyrir vikið komum við með aðra nálgun. Við ákváðum að láta mypy virka fljótt, jafnvel í viðurvist „ósjálfstæðisflækja“. Við náðum þessu markmiði með því að nota mypy púkann. Púkinn er miðlaraferli sem útfærir tvo áhugaverða eiginleika. Í fyrsta lagi geymir það upplýsingar um allan kóðagrunninn í minni. Þetta þýðir að í hvert skipti sem þú keyrir mypy þarftu ekki að hlaða inn skyndiminni gögnum sem tengjast þúsundum innfluttra ósjálfstæðis. Í öðru lagi greinir hann vandlega, á stigi lítilla byggingareininga, háðirnar á milli aðgerða og annarra eininga. Til dæmis, ef fallið foo kallar fall bar, þá er það háð foo frá bar. Þegar skrá breytist, vinnur púkinn fyrst, í einangrun, aðeins breyttu skránni. Það skoðar síðan sýnilegar breytingar á þeirri skrá, svo sem breyttar aðgerðarundirskriftir. Púkinn notar aðeins nákvæmar upplýsingar um innflutning til að tvítékka þær aðgerðir sem nota breytta aðgerðina í raun. Venjulega, með þessari nálgun, þarftu að athuga mjög fáar aðgerðir.

Það var ekki auðvelt að útfæra þetta allt saman, þar sem upphaflega mypy útfærslan var mikil áhersla á að vinna úr einni skrá í einu. Við þurftum að takast á við margar landamæraaðstæður, sem krafðist endurtekinna athugana í þeim tilvikum þar sem eitthvað breyttist í kóðanum. Til dæmis gerist þetta þegar bekk er úthlutað nýjum grunnflokki. Þegar við gerðum það sem við vildum gátum við stytt framkvæmdartíma flestra stigvaxandi athugana niður í nokkrar sekúndur. Þetta þótti okkur stór sigur.

Enn meiri framleiðni!

Ásamt fjarlægu skyndiminni sem ég ræddi hér að ofan leysti mypy púkinn nánast alveg vandamálin sem koma upp þegar forritari keyrir oft tegundaskoðun og gerir breytingar á fáum skrám. Hins vegar var afköst kerfisins í óhagstæðasta notkunartilvikinu enn langt frá því að vera ákjósanleg. Hrein ræsing á mypy gæti tekið meira en 15 mínútur. Og þetta var miklu meira en við hefðum verið ánægð með. Í hverri viku versnaði ástandið þar sem forritarar héldu áfram að skrifa nýjan kóða og bæta athugasemdum við núverandi kóða. Notendur okkar voru enn hungraðir í meiri frammistöðu, en við vorum ánægð að hitta þá á miðri leið.

Við ákváðum að fara aftur í eina af fyrri hugmyndum varðandi mypy. Nefnilega að breyta Python kóða í C kóða. Tilraunir með Cython (kerfi sem gerir þér kleift að þýða kóða skrifaðan í Python yfir í C ​​kóða) gáfu okkur enga sjáanlega hraða, svo við ákváðum að endurvekja hugmyndina um að skrifa okkar eigin þýðanda. Þar sem mypy kóðagrunnurinn (skrifaður í Python) innihélt nú þegar allar nauðsynlegar tegundaskýringar, töldum við að það væri þess virði að reyna að nota þessar athugasemdir til að flýta fyrir kerfinu. Ég bjó fljótt til frumgerð til að prófa þessa hugmynd. Það sýndi meira en 10-falda aukningu á frammistöðu á ýmsum örviðmiðum. Hugmyndin okkar var að setja saman Python einingar í C ​​einingar með Cython, og breyta tegundaskýringum í tegundaskoðun (venjulega eru tegundaskýringar hunsaðar á keyrslutíma og aðeins notaðar af tegundaskoðunarkerfum). Við ætluðum í raun að þýða mypy útfærsluna frá Python yfir á tungumál sem var hannað til að vera statískt vélritað, sem myndi líta út (og að mestu leyti virka) nákvæmlega eins og Python. (Þessi tegund af þvermálsflutningi er orðin einhver hefð í mypy verkefninu. Upprunalega mypy útfærslan var skrifuð í Alore, síðan var til setningafræðilegur blendingur af Java og Python).

Að einblína á CPython viðbótina API var lykillinn að því að missa ekki verkefnastjórnunargetu. Við þurftum ekki að útfæra sýndarvél eða nein bókasöfn sem mypy þurfti. Að auki myndum við enn hafa aðgang að öllu Python vistkerfinu og öllum verkfærum (eins og pytest). Þetta þýddi að við gætum haldið áfram að nota túlkað Python kóða meðan á þróun stendur, sem gerir okkur kleift að halda áfram að vinna með mjög hratt mynstur við að gera kóðabreytingar og prófa hann, frekar en að bíða eftir að kóðann sé settur saman. Það leit út fyrir að við værum að gera frábært starf við að sitja á tveimur stólum, ef svo má segja, og okkur þótti vænt um það.

Þjálfarinn, sem við kölluðum mypyc (þar sem hann notar mypy sem framhlið til að greina tegundir), reyndist mjög vel heppnað verkefni. Í heildina náðum við um það bil 4x hraðaupphlaupum fyrir tíðar mypy keyrslur án skyndiminni. Að þróa kjarna mypyc verkefnisins tók lítið teymi af Michael Sullivan, Ivan Levkivsky, Hugh Hahn og sjálfum mér um 4 almanaksmánuði. Þetta magn af vinnu var miklu minna en það sem hefði þurft til að endurskrifa mypy, til dæmis í C++ eða Go. Og við þurftum að gera mun færri breytingar á verkefninu en við hefðum þurft að gera þegar við endurskrifuðum það á öðru tungumáli. Við vonuðum líka að við gætum komið mypyc á það stig að aðrir Dropbox forritarar gætu notað það til að safna saman og flýta fyrir kóðanum sínum.

Til að ná þessu frammistöðustigi þurftum við að beita áhugaverðum verkfræðilausnum. Þannig getur þýðandinn flýtt fyrir mörgum aðgerðum með því að nota hraðvirkar C-smíðar á lágu stigi. Til dæmis er samsett fallkall þýtt yfir í C ​​fallkall. Og slíkt símtal er miklu fljótlegra en að kalla túlkað fall. Sumar aðgerðir, eins og uppflettingar í orðabókum, fólu enn í sér að nota reglulega C-API símtöl frá CPython, sem voru aðeins örlítið hraðari þegar þau voru sett saman. Okkur tókst að útrýma viðbótarálaginu á kerfið sem skapaðist við túlkun, en þetta í þessu tilfelli gaf aðeins lítinn ávinning hvað varðar frammistöðu.

Til að bera kennsl á algengustu „hægu“ aðgerðirnar framkvæmdum við kóðasnið. Vopnaðir þessum gögnum reyndum við annað hvort að fínstilla mypyc þannig að það myndi búa til hraðari C kóða fyrir slíkar aðgerðir, eða endurskrifa samsvarandi Python kóða með hraðari aðgerðum (og stundum höfðum við einfaldlega ekki nógu einfalda lausn fyrir það eða annað vandamál) . Að endurskrifa Python kóðann var oft auðveldari lausn á vandamálinu en að láta þýðandann framkvæma sömu umbreytingu sjálfkrafa. Til lengri tíma litið vildum við gera margar af þessum umbreytingum sjálfvirkar, en á þeim tíma einbeitum við okkur að því að flýta fyrir mypy með lágmarks fyrirhöfn. Og þegar við fórum í átt að þessu markmiði skárum við nokkur horn.

Til að halda áfram ...

Kæru lesendur! Hver var tilfinning þín af mypy verkefninu þegar þú frétti af tilvist þess?

Leiðin til að slá inn 4 milljón línur af Python kóða. 2. hluti
Leiðin til að slá inn 4 milljón línur af Python kóða. 2. hluti

Heimild: www.habr.com

Bæta við athugasemd