Çfarë mësova nga krijimi i një aplikacioni në internet duke eksperimentuar me përdorimin e shumë punonjësve të uebit (të ngjashëm me një sistem aktorësh nga ana e klientit)

Prezantimi

Në këtë artikull do të tregoj për disa eksperimente që bëra duke krijuar një aplikacion në internet të quajtur cloc-web, mund ta gjeni "këtu".
Aplikacioni është një faqe e vetme ueb që zbaton një shumë versioni i thjeshtë i CLOC (Count Lines Of Code). Nëse nuk e dini se për çfarë po flas, ju sugjeroj të shkoni të shihni origjinalin "këtu", mendoj se është një bibliotekë "legjendare". Gjithsesi, një TLDR është se është një softuer që merr një skedar ose një drejtori si hyrje dhe kthen numrin e rreshtave të kodit (me disa informacione shtesë, si komentet janë të ndara nga kodi) si dalje.

Mohimi i përgjegjësisë: biblioteka origjinale është E MREKULLUESHME, dhe në asnjë mënyrë aplikacioni im nuk ka për qëllim të jetë një përpjekje për të bërë diçka më të mirë, imi ishte thjesht një eksperiment, nëse jeni të interesuar ta përdorni për CLOC një nga projekte, dijeni që versioni im ka SHUMË veçori që mungojnë, kështu që ose përdorni "origjinalin" ose këtë dy zbatim të ri të lezetshëm, "një në Rust" dhe "një në Go" për diçka serioze.

Pse

CLOC është një lloj aplikacioni i lezetshëm për të mësuar një gjuhë të re për shembull, kështu që është diçka që e përdor herë pas here për eksperimente, të detyron të prekësh aspekte të ndryshme të një gjuhe dhe është argëtuese për ta ndërtuar.
Për natyrën e saj, ju do të përballet gjithashtu me problemin e mundshëm të ngadalësisë së aplikacionit, me këtë dua të them që nëse doni të numëroni linjat e kodit të një projekti të madh, koha mund të zgjasë shpejt dhe ky është një rast i përsosur përdorimi për punonjësit e uebit në mendimi im:
Imagjinoni të shtypni butonin për të CLOC një projekt, nëse duhen 10 sekonda dhe UI është i ngrirë gjatë gjithë kohës, ndoshta nuk do t'ju pëlqejë ai aplikacion në internet, apo jo? Nëse, në vend të kësaj, në këto 10 sekonda, ka një ngarkues ose diçka tjetër që ju bën të dini se diçka po ndodh, ai bëhet i pranueshëm (të paktën ju e dini se po bën diçka).

Kur fillova projektin, me sa di unë, nuk kishte asnjë aplikacion në internet që zbatonte CLOC tërësisht në anën e klientit në shfletues (çdo version ishte aplikacion CLI ose klient që më pas bën llogaritjen nga ana e serverit).
Kjo ndoshta zbatohet nga fakti që shfletuesit nuk kishin API të këndshme për të bashkëvepruar me sistemin e skedarëve deri në ditët e sotme.
Me Chrome 86 (lëshuar në tetor 2020), një grup i ri API i quajtur File System Access API u lëshuan, dhe ato janë të mahnitshme. Doja t'i provoja sepse mendoj se ky grup API-sh mundëson një grup të ri aplikacionesh ueb që ndërveprojnë me sistemin e skedarëve (p.sh. redaktorë më të mirë të uebit).

Kujdes gjithashtu që këto API nuk mbështeten ende gjerësisht, kështu që jo të gjitha pajisjet do t'ju lejojnë të provoni aplikacionin tim.

Shënim për standardet

Të gjitha të dhënat që do të lexoni më poshtë e konsiderojnë Vuetify monorepo si projektin e numëruar. Nga testet e mia, duket se ka pothuajse 7.000 skedarë dhe më shumë se 850.000 rreshta kodi (në kohën kur kam zhvilluar aplikacionin), nuk është një depo e madhe, por as e vogël. Unë nuk po numëroj disa skedarë dhe dosje, p.sh., po injoroj node_modules.
Vlerat merren si një mesatare midis 10 ekzekutimeve në mac-in tim.

Së pari, versioni i thjeshtë me një punonjës në internet

Versioni i parë nuk është as një eksperiment, është zbatimi më i drejtpërdrejtë që mund të krijoni (duke përfshirë ende punonjës të uebit), aplikacioni krijon një punonjës të internetit dhe kur përdoruesi zgjedh dosjen e projektit për të numëruar, DirectoryHandle dërgohet nga tema kryesore te punonjësi i uebit. Ky punonjës më pas lexon në mënyrë rekursive numrin e rreshtave të të gjithë skedarëve në drejtorinë e specifikuar.
Kjo zgjidhje është shumë e thjeshtë dhe funksionon mirë, por nuk është e shpejtë, rezultatin e marr në 8– 9 sekonda, dhe nuk më pëlqen që ne nuk po shfrytëzojmë arkitekturat shumëbërthamore të pajisjeve moderne.
Pika e mirë është se ne e mbajmë ndërfaqen e përdoruesit interaktive dhe të shkathët duke ekzekutuar gjithçka brenda një punonjësi në internet.

Versioni i dytë, një punonjës në internet për skedar

Për versionin e dytë doja të provoja diçka pothuajse ‘ekstreme’. I frymëzuar nga modeli i aktorit doja të provoja të krijoja një punëtor për skedar. Nëse kjo tingëllon e çmendur, keni të drejtë, por prapë doja të provoja, sepse pashë në të kaluarën time disa aplikacione backend që përdorën sasi të mëdha aktorësh.

Më lejoni të them fillimisht se kjo është e mundur vetëm sepse DirectoryHandle është i serializueshëm (gjithashtu FileHandle) dhe u habita shumë që këto referenca janë të serializueshme (faleminderit njerëzve që krijoi këtë grup API).

Në këtë zgjidhje unë kam një punonjës "kryesor" të uebit, ai kalon nëpër të gjitha drejtoritë dhe skedarët, për çdo skedar ai krijon një punonjës të ri dhe i dërgon atij FileHandle. Punonjësi i ri vetëm numëron numrin e rreshtave dhe ia kthen rezultatet punëtorit kryesor. Kur punëtori kryesor merr të gjitha rezultatet nga punëtorët e krijuar, ai bashkon gjithçka dhe ia dërgon rezultatin përfundimtar aplikacionit në fillin kryesor për t'i treguar përdoruesit.

Ky version ishte një dështim i plotë (siç pritej). Ishte e vështirë të numëroja monorepo Vuetify në Mac-in tim, shumë i sigurt se po lindja shumë punëtorë (1 për skedar, pra rreth 850.000 max teorikisht).

Versioni i tretë, grupi i punëtorëve

Është e qartë se nuk mund të krijoj 1 punëtor për skedar (dhe ndoshta nuk ka kuptim), por dua të shfrytëzoj më shumë punë paralele dhe të përdor arkitekturat me shumë bërthama që kanë kompjuterët e rinj.
Kështu që vendosa të krijoj një grup punëtorësh (provova numra të ndryshëm, 4, 8, 16 për të parë nëse kisha rezultate të ndryshme) që mund t'i përdorë punëtori kryesor. Kur aplikacioni fillon, ai krijon punëtorin kryesor dhe ai krijon grupin e punëtorëve. Ngjashëm me versionin e mëparshëm, kur punonjësi kryesor merr hyrjen e përdoruesit, ai kalon nëpër drejtori dhe skedarë dhe i dërgon FileHandle një punonjësi tjetër, këtë herë të zgjedhur nga grupi.
Doja për t'u siguruar që të zgjedh një punëtor të lirë, jo një që tashmë po numëron diçka, për ta arritur këtë kam provuar dy zgjidhje:

Në pritje të punëtorëve të lirë me premtime

Kjo është qasja e parë që më erdhi në mendje, sepse natyra e premtimeve, dukej e përsosur.
Kur punonjësi kryesor i dërgon FileHandle një punonjësi, ai shoqëron një Premtim për të dhe e zgjidh atë vetëm kur të marrë përgjigjen, kështu që ndërsa ka një premtim në pritje, ai nuk mund të dërgojë një tjetër File Handle.

Nuk jam i sigurt nëse kam gabuar diçka, por këto zgjidhje po më sjellin rezultate shumë të këqija:

  • me 8 punëtorë u deshën 25–30 sekonda
  • me 16 punëtorë u deshën 38–42 sekonda

Rritja e numrit të punëtorëve në fakt po degradonte performancën. Nuk mund ta kuptoja se nga çfarë shkaktoi kjo, mund të ketë qenë një gabim memec nga imi.

Më pas vendos të provoj një qasje tjetër:

Në pritje të punëtorëve të lirë me votim

U përpoqa të ndryshoja "pritjen e premtimeve" me një "mekanizëm votimi" për të marrë punëtorët pa pagesë, nuk prisja që kjo të përmirësonte asgjë, por u habita shumë kur pashë matjet.

  • me 8 punëtorë u deshën rreth 3,9 sekonda
  • me 16 punëtorë rreth 3.0s
  • me 24 punëtorë rreth 3.5s

Këto janë rezultate të mira, po i duhet më pak se gjysma e kohës për zgjidhjen me vetëm një punëtor, unë isha mjaft i lumtur për këtë.
Nuk jam i sigurt nëse qasja e mëparshme që përdorte Promises ishte më e ngadaltë për shkak të disa shpenzimeve në API-në e premtimit , në fund po krijojmë shumë prej tyre, por është vetëm një hipotezë.

Versioni i katërt, numëroni numrin e skedarëve dhe prisni atë sasi të përgjigjeve të punonjësve

Versioni i katërt (dhe i fundit) funksionon pak më ndryshe nga ai i mëparshmi, këtë herë nuk po përpiqem të përdor një punëtor falas, po i dërgoj FileHandles secilit punonjës në mënyrë të vazhdueshme (edhe nëse ata janë ende duke numëruar), më pas presin të gjitha rezultatet.
Pra, punonjësi kryesor i uebit përsërit përmes sistemit të skedarëve, për çdo skedar të gjetur, ai rrit një numër që përfaqëson numrin e punëtorëve që presin përgjigjen, më pas ai dërgon FileHandle te një punëtori (i zgjedhur me një formë të rrumbullakët).
Kur një punonjës përfundon numërimin e skedarëve, ai ia dërgon të dhënat përsëri punonjësit kryesor, ky i fundit kontrollon nëse çdo punëtor është përgjigjur, nëse po i kthen të gjitha rezultatet e grumbulluara në fillin kryesor për t'i shfaqur përdoruesit.

Rezultatet:

  • me 8 punëtorë: 4.5s
  • me 16 punëtorë: 4.2s
  • me 24 punëtorë: 4.2s

Sinqerisht, prisja që kjo zgjidhje të ishte më e shpejtë në krahasim me atë të sondazhit (sepse nuk ka ndonjë mekanizëm ‘pritje’), por pas disa arsyetimit mund të kem gjetur një motivim të mundshëm.
Në këtë zgjidhje ne po ia dërgojmë skedarin e parë punëtorit të parë, të dytin tek i dyti, dhe (nëse kemi 8 punëtorë) të nëntën punëtorit të parë përsëri (round robin), kështu që mund të ketë mundësi që një nga punëtorët është i pafat dhe merr të gjithë dosjen më të rëndë të projektit, kjo do të çonte në një pengesë të vogël nga ana e tij, përsëri kjo është vetëm një hipotezë.

konkluzioni

Ishte shumë qesharake të ndërtoje cloc-web, dhe mund të luani me të këtu https://cloc-web.netlify.app/ (funksionon 100% nga ana e klientit; nuk dërgohen të dhëna askund, kështu që mos Shqetësohuni për sekretet etj. Mund të shihni në rrjet vetëm një kërkesë http që unë përdor për të mbledhur analitikë dhe gjurmim të gabimeve).
Versioni i vendosur përdor zgjidhjen e tretë (me sondazh), nëse hapni 'cilësimet ', mund të luani gjithashtu me dimensionin e grupit të punëtorëve dhe të vendosni disa skedarë që të shpërfillen.

Nga rezultatet e marra me qasje të ndryshme, mund të shoh se ne mund të kemi avantazhe nga ana e klientit (përsa i përket performancës) duke përdorur punonjës të shumtë në ueb për të shfrytëzuar pajisjet me shumë fije.
Përmirësimet nuk janë të pabesueshme dhe (ndoshta) Kompleksiteti më i lartë i bazës së kodit nuk vlen 99% e rasteve të përdorimit, por mund të ketë disa aplikacione të veçanta ueb që mund ta shfrytëzojnë këtë.
Unë ende rekomandoj përdorimin e të paktën një punonjësi të uebit për të ekzekutuar procese të rënda nga ana e klientit, duke marrë parasysh që në ditët e sotme është e thjeshtë të integrohen punëtorët në aplikacionet në ueb duke përdorur grupe moderne (ose edhe më mirë nëse përdorni korniza si Next Nuxt dhe të ngjashme… P.sh. https://nextjs.org/docs/basic-features/script#offloading-scripts- për-një-punëtor në internet-eksperimental)

Burimet

Më shumë përmbajtje në PlainEnglish.io.

Regjistrohu për buletinin tonë javor falas. Na ndiqni në Twitter, LinkedIn, YouTube, dhe Discord .

I interesuar në shkallëzimin e fillimit të softuerit tuaj? Shikoni Circuit.