Rêya kontrolkirina 4 mîlyon xetên koda Python. Beş 2

Îro em beşa duyemîn a wergera materyalê diweşînin ka Dropbox çawa ji bo çend mîlyon rêzikên koda Python kontrolkirina tîpê organîze kir.

Rêya kontrolkirina 4 mîlyon xetên koda Python. Beş 2

Beşa yekê bixwînin

Piştgiriya celebê fermî (PEP 484)

Me ceribandinên xwe yên yekem ên cidî bi mypy re li Dropbox-ê di dema Hack Week 2014 de pêk anî. Hefteya Hack bûyerek hefteyekê ye ku ji hêla Dropbox ve tê organîze kirin. Di vê demê de, karmend dikarin li ser tiştê ku ew dixwazin bixebitin! Hin projeyên teknolojiyê yên herî navdar ên Dropbox di bûyerên bi vî rengî de dest pê kirin. Di encama vê ceribandinê de, me encam da ku mypy sozdar xuya dike, her çend proje hîn ji bo karanîna berfireh ne amade ye.

Di wê demê de, ramana standardkirina pergalên hinarkirinê yên Python li hewa bû. Wekî ku min got, ji Python 3.0-ê ve gengaz bû ku ji bo fonksiyonan şîroveyên tîpan bikar bînin, lê ev tenê îfadeyên kêfî bûn, bêyî hevoksazî û semantîkên diyarkirî. Di dema pêkanîna bernameyê de, ev şîrovekirin, bi piranî, bi hêsanî hatin paşguh kirin. Piştî Hefteya Hackê, me dest bi xebata standardkirina semantîkê kir. Ev xebat bû sedema derketina holê PEP 484 (Guido van Rossum, Łukasz Langa û min li ser vê belgeyê hevkarî kir).

Mebestên me ji du aliyan ve dihatin dîtin. Pêşîn, me hêvî dikir ku tevahiya ekosîstema Python bikaribe ji bo karanîna tîpên tîpan nêzîkatiyek hevpar bipejirîne (têgehek ku di Python de wekî hevwateya "navdêrên celeb" tê bikar anîn). Ev, ji ber xetereyên gengaz, dê ji karanîna gelek nêzîkatiyên hevûdu nakok çêtir be. Ya duyemîn, me xwest ku bi gelek endamên civata Python re bi eşkere mekanîzmayên annotation tîpan nîqaş bikin. Ev xwestek hinekî ji hêla wê yekê ve hatî ferman kirin ku em naxwazin ji ramanên bingehîn ên zimên di çavên girseyên berfireh ên bernamenûsên Python de mîna "rahîdan" xuya bikin. Ew zimanek dînamîkî ye ku bi tîpên dînamîkî tê zanîn, wekî "dok typing". Di civakê de, di destpêkê de, helwestek hinekî gumanbar li hember ramana tîpkirina statîk nekare bibe alîkar. Lê ew hest di dawiyê de kêm bû piştî ku eşkere bû ku nivîsandina statîk dê ne mecbûrî be (û piştî ku mirov fêm kir ku ew bi rastî bikêr e).

Hevoksaziya hint a tîpê ya ku di dawiyê de hate pejirandin pir dişibihe ya ku mypy wê demê piştgirî dikir. PEP 484 bi Python 3.5 di 2015 de hate berdan. Python êdî ne zimanekî dînamîkî bû. Ez dixwazim vê bûyerê wekî qonaxek girîng di dîroka Python de bifikirim.

Destpêka koçberiyê

Di dawiya 2015-an de, Dropbox tîmek sê kesan çêkir ku li ser mypy bixebitin. Di nav wan de Guido van Rossum, Greg Price û David Fisher hebûn. Ji wê gavê û pê de, rewş pir zû dest pê kir. Astengiya yekem a mezinbûna mypy performansê bû. Wekî ku min li jor destnîşan kir, di rojên destpêkê yên projeyê de ez fikirîm ku ez pêkanîna mypy li C-yê wergerînim, lê ev raman ji bo nuha ji navnîşê derbas bû. Em bi xebitandina pergalê bi karanîna wergêrê CPython, ku ji bo amûrên mîna mypy têra xwe zû nake, asê mabûn. (Projeya PyPy, pêkanîna Python-a alternatîf a bi berhevkarek JIT re, alîkariya me jî nekir.)

Xweşbextane, hin pêşkeftinên algorîtmîkî li vir hatine alîkariya me. Yekem "lezker"a hêzdar pêkanîna kontrolkirina zêde bû. Fikra li pişt vê pêşkeftinê hêsan bû: heke hemî girêdanên modulê ji xebata berê ya mypy neguherîbin, wê hingê em dikarin dema ku bi girêdanan re dixebitin daneyên ku di dema xebitandina berê de veşartibûn bikar bînin. Me tenê hewce bû ku li ser pelên guhertî û pelên ku bi wan ve girêdayî ne vekolîna tîpan bikin. Mypy piçekî pêş de çû: heke navbeynkariya derveyî ya modulek neguherî, mypy texmîn kir ku modulên din ên ku vê modulê îtxal kirine ne hewce ne ku ji nû ve werin kontrol kirin.

Kontrolkirina zêdekirî dema ku jimareyên mezin ên kodên heyî şîrove dikin gelek alîkariya me kiriye. Mesele ev e ku ev pêvajo bi gelemperî gelek rêzikên dubare yên mypy-yê vedihewîne ji ber ku şîrove gav bi gav li kodê têne zêdekirin û hêdî hêdî çêtir dibin. Rêvekirina yekem a mypy hîn jî pir hêdî bû ji ber ku gelek pêwendiyên wê hebûn ku werin kontrol kirin. Dûv re, ji bo baştirkirina rewşê, me mekanîzmayek cachkirina dûr pêk anî. Ger mypy destnîşan bike ku îhtîmal e ku cacheya herêmî kevn be, ew wêneya cache ya heyî ya ji bo tevaya bingehê kodê ji depoya navendî dakêşîne. Dûv re ew bi karanîna vê wêneyê vekolînek zêde dike. Vê yekê me gavek din a mezin ber bi zêdekirina performansa mypy ve avêt.

Ev serdemek pejirandina bilez û xwezayî ya kontrolkirina celebê li Dropbox bû. Di dawiya sala 2016-an de, me jixwe nêzî 420000 rêzikên koda Python-ê bi şîroveyên tîpan re hebûn. Gelek bikarhêner ji bo kontrolkirina tîpê bi coş bûn. Zêdetir û bêtir tîmên pêşkeftinê Dropbox mypy bikar tînin.

Wê demê her tişt baş xuya dikir, lê hîna jî gelek tişt hebûn ku em bikin. Me dest bi pêkanîna anketên bikarhênerên navxweyî yên periyodîk kir da ku em qadên pirsgirêkê yên projeyê nas bikin û fêm bikin ka çi pirsgirêk divê pêşî werin çareser kirin (ev pratîk îro jî di pargîdaniyê de tê bikar anîn). Ya herî girîng, wekî ku diyar bû, du peywir bûn. Ya yekem, ji me re pêdiviya bêtir celebê kodê hebû, ya duyemîn, ji me re hewce bû ku mypy zûtir bixebite. Bê guman eşkere bû ku xebata me ya ji bo bilezkirina mypy û bicîhkirina wê di projeyên pargîdaniyê de hîn ji temambûnê dûr bû. Em ji girîngiya van her du karan baş dizanin, dest bi çareseriya wan kirin.

Berhemdariya bêtir!

Kontrolên zêdebûyî mypy zûtir kir, lê amûr hîn jî têra xwe zû nebû. Gelek kontrolên zêde bi qasî deqeyekê dom kir. Sedema vê yekê îthalata çerxa bû. Ev belkî dê kesê ku bi kodên mezin ên ku di Python-ê de hatine nivîsandin de xebitiye şaş neke. Me bi sedan modulên me hebûn, ku her yek ji wan nerasterast hemî yên din îthal dikirin. Ger pelek di çerxa importê de were guheztin, mypy neçar bû ku hemî pelên di wê dorpêçê de, û bi gelemperî modulên ku modulên ji wê lûkê derdixin, bişopîne. Yek çerxek wusa "tevliheviya girêdayîbûnê" ya navdar bû ku li Dropbox-ê bû sedema gelek tengasiyan. Gava ku ev avahî çend sed modul dihewand, dema ku ew rasterast an nerasterast, gelek ceribandin hate îtxal kirin, ew di koda hilberînê de jî hate bikar anîn.

Me îhtîmala "veqetandina" girêdayiyên dorhêl dihesiband, lê me nebûn ku em bikin. Zêde koda ku em pê nizanin hebû. Di encamê de, em bi nêzîkatiyek alternatîf derketin. Me biryar da ku di nav hebûna "tevliheviyên girêdayîbûnê" de jî, mypy zû bixebite. Me bi karanîna mypy daemon gihîşt vê armancê. Daemon pêvajoyek serverê ye ku du kapasîteyên balkêş pêk tîne. Pêşîn, ew agahdariya li ser tevahiya kodê di bîranînê de hilîne. Ev tê vê wateyê ku her gava ku hûn mypy-yê dimeşînin, ne hewce ye ku hûn daneyên cache yên girêdayî bi hezaran girêdanên îthalkirî bar bikin. Ya duyemîn, ew bi baldarî, di asta yekîneyên piçûk ên avahîsaziyê de, girêdayîbûna di navbera fonksiyonan û pêkhateyên din de analîz dike. Ji bo nimûne, eger fonksiyonê foo fonksiyonek bang dike bar, wê demê girêdayîbûnek heye foo ji bar. Dema ku pelek diguhezîne, pêşî daemon, bi veqetandî, tenê pelê hatî guherandin pêvajoyê dike. Dûv re ew li guhertinên xuyang ên derveyî yên wê pelê dinêre, wek nimûneyên fonksiyonê yên guherî. Daemon agahdariya hûrgulî di derbarê importan de tenê bikar tîne da ku wan fonksiyonên ku bi rastî fonksiyona guhertî bikar tînin ducar kontrol bike. Bi gelemperî, bi vê nêzîkbûnê re, divê hûn pir hindik fonksiyonan kontrol bikin.

Bicîhanîna van hemîyan ne hêsan bû, ji ber ku pêkanîna mypy ya orîjînal bi giranî li ser pêvajoyek pelê di demekê de bû. Diviya bû ku em bi gelek rewşên sînorî re mijûl bibin, rûdana wan di rewşên ku tiştek di kodê de guherî de hewcedarî kontrolên dubare dikir. Mînakî, ev diqewime dema ku çînek çînek bingehîn a nû tê veqetandin. Gava ku me tiştê ku me dixwest kir, me karîbû wextê pêkanîna piraniya kontrolên zêde bi tenê çend hûrdeman kêm bikin. Ev ji me re serkeftinek mezin xuya dikir.

Hilberîna hê bêtir!

Digel cachkirina dûr a ku min li jor behs kir, mypy daemon hema hema bi tevahî pirsgirêkên ku çêdibin dema ku bernamenûsek pir caran kontrolkirina tîpê dimeşîne, guheztina li hejmarek piçûk pelan çêdike, çareser kir. Lêbelê, performansa pergalê di doza karanîna herî kêm de hîn jî ji çêtirîn dûr bû. Destpêkek paqij a mypy dikare zêdetirî 15 hûrdem bigire. Û ev ji ya ku em ê pê kêfxweş bibûna pir zêdetir bû. Her hefte rewş xirabtir dibû ji ber ku bernamenûs berdewam nivîsandina kodên nû û lêzêdekirina şiroveyan li koda heyî dikirin. Bikarhênerên me hîn jî ji bo performansa bêtir birçî bûn, lê em kêfxweş bûn ku bi nîvê rê bi wan re hevdîtin kirin.

Me biryar da ku em vegerin yek ji ramanên berê yên di derbarê mypy de. Ango, ji bo veguhertina koda Python nav koda C. Ceribandina Cython (pergalek ku destûrê dide te ku hûn koda ku bi Python hatî nivîsandin veguhezînin koda C-yê) lezek xuyayî neda me, ji ber vê yekê me biryar da ku em ramana nivîsandina berhevkarê xwe vejînin. Ji ber ku bingeha koda mypy (bi Python-ê hatî nivîsandin) jixwe hemî şiroveyên cûrbecûr yên pêwîst dihewand, me fikirîn ku dê hêja be ku em van şîroveyan bikar bînin da ku pergalê bileztir bikin. Min zû prototîpek çêkir ku vê ramanê biceribînim. Ew ji 10-qatî zêdebûnek performansê li ser pîvanên cihêreng ên mîkro nîşan da. Fikra me ev bû ku em modulên Python bi modulên C-yê bi karanîna Cython berhev bikin, û şîroveyên tîpan veguherînin kontrolên tîpa-dema xebitandinê (bi gelemperî şiroveyên tîpan di dema xebitandinê de têne paşguh kirin û tenê ji hêla pergalên kontrolkirina tîpan ve têne bikar anîn). Me bi rastî plan kir ku em pêkanîna mypy ji Python wergerînin zimanek ku ji bo ku bi awayekî statîkî were nivîsandin hatî çêkirin, ku dê tam mîna Python xuya bike (û, bi piranî, bixebite). (Ev cûre koçkirina nav-ziman bûye tiştekî kevneşopiya projeya mypy. Pêkanîna orîjînal a mypy di Alore de hate nivîsandin, piştre hevrêzek hevoksaziya Java û Python hebû).

Balkêşkirina li ser dirêjkirina CPython API-ya sereke bû ku hûn kapasîteyên rêveberiya projeyê winda nekin. Ne hewce bû ku me makîneyek virtual an pirtûkxaneyên ku mypy hewce dike bicîh bînin. Wekî din, em ê hîn jî bigihîjin tevahiya ekosîstema Python û hemî amûran (wek pytest). Ev tê vê wateyê ku em dikarin di dema pêşkeftinê de karanîna koda Python-a şirovekirî bidomînin, ku rê dide me ku em bi şêwazek pir bilez a çêkirina guheztina kodê û ceribandina wê berdewam bikin, li şûna ku li benda berhevkirina kodê bin. Wusa dixuye ku em li ser du kursiyan rûniştin, bi vî rengî, karek mezin dikirin û me jê hez dikir.

Berhevkarê ku me jê re digot mypyc (ji ber ku ew mypy wekî pêşekek ji bo analîzkirina celeban bikar tîne), projeyek pir serfiraz derket. Bi tevayî, me bi qasî 4x leza ji bo rêveçûna mypy-ya pir caran bêyî cachkirinê bi dest xist. Pêşxistina bingeha projeya mypyc, tîmek piçûk Michael Sullivan, Ivan Levkivsky, Hugh Hahn û ez bi qasî 4 mehên salnameyê girt. Ev mîqdara kar ji ya ku ji nû ve nivîsandina mypy-ê hewce bû, ji bo nimûne, di C++ an Go de pir piçûktir bû. Û diviyabû ku em pir kêmtir guhertinan di projeyê de bikin ji ya ku me diviyabû dema ku wê bi zimanekî din ji nû ve binivîsanda. Di heman demê de me hêvî dikir ku em karibin mypyc bigihînin astek wusa ku bernamenûsên Dropbox-ê yên din karibin wê bikar bînin da ku koda xwe berhev bikin û bilezînin.

Ji bo gihîştina vê astê performansê, me neçar ma ku hin çareseriyên endezyariyê yên balkêş bicîh bînin. Ji ber vê yekê, berhevkar dikare bi karanîna avahîyên C-ya bilez û nizm, gelek xebatan bileztir bike. Mînak bangek fonksiyonek berhevkirî vedigere bangek fonksiyonek C. Û bangek wusa ji bangkirina fonksiyonek şirovekirî pir zûtir e. Hin operasyonan, wek lêgerînên ferhengê, hîn jî bi karanîna bangên C-API-ya birêkûpêk ji CPython-ê re têkildar in, ku dema berhev kirin tenê hindiktir zûtir bûn. Me karîbû bargiraniya zêde ya li ser pergalê ku ji hêla şîrovekirinê ve hatî afirandin ji holê rakin, lê ev di vê rewşê de di warê performansê de tenê destkeftiyek piçûk da.

Ji bo naskirina operasyonên "hêdî" yên herî gelemperî, me profîla kodê pêk anî. Çekdar bi van daneyan, me hewl da ku an mypyc biguhezînin da ku ew ji bo operasyonên weha koda C-ya bileztir çêbike, an jî koda Python-a têkildar bi karanîna operasyonên zûtir ji nû ve binivîsîne (û carinan me ji bo wê an pirsgirêkek din çareseriyek têra xwe sade nebû) . Ji nû ve nivîsandina koda Python bi gelemperî ji pirsgirêkê re çareseriyek hêsantir bû ji bilî ku berhevkar bixweber heman veguherînê pêk bîne. Di demek dirêj de, me xwest ku em gelek ji van veguherînan otomatîk bikin, lê wê demê em balê dikişînin ser lezkirina mypy bi hewildanek hindiktirîn. Û di çûna ber bi vê armancê de, me çend goşe qut kirin.

Ez bêtir ji te hez dikim…

Xwendevanên delal! Gava ku hûn hebûna wê fêr bûn, nerînên we ji projeya mypy çi bûn?

Rêya kontrolkirina 4 mîlyon xetên koda Python. Beş 2
Rêya kontrolkirina 4 mîlyon xetên koda Python. Beş 2

Source: www.habr.com

Add a comment